Adobe Interview Experience: MTS-2 Android
Anonymous User
419

Years of Experience: 2 YOE

Current Role: Android Engineer, Startup (SDE-III)

Result: Offer Received

Round 1: Android Basics Deep Dive

Format: Online (MS Teams) · Duration: 1 hour

Introduction

The round started with a brief introduction — my career journey so far and my open-source contribution. We then went deeper into my work at my organization: the overall team structure, the size of the Android team, and what a typical day looks like for me.

Singleton Pattern

  • What is a singleton class? Followed by implementing a basic singleton in Java.

  • Thread safety of the implementation — how do we ensure the singleton is thread-safe?

  • Singletons in Kotlin — different approaches:

  • object declaration

  • Java-style singleton

  • synchronized block — we discussed that this is JVM-specific, and since Kotlin is multiplatform, platform-specific locking mechanisms would be needed for KMP targets.


class Database {

    private static Database INSTANCE;

    private Database() {}

    static Database getInstance() {
        if (INSTANCE == null) INSTANCE = new Database();
        return INSTANCE;
    }

}
object Database

App Performance

How do we measure the performance of an Android app (or any app in general)?

  • Memory leaks

  • UI jank

  • ANR — main thread blocked for more than 5 seconds

  • Crashes

  • UX degradation from long-running work — slow DB queries, IO, heavy computation

How do we measure and diagnose these? Using tools like Crashlytics and App Inspection in Android Studio.

Memory Leaks

  • What is a memory leak? Detailed discussion with Android-specific examples.

  • Scenarios that commonly cause leaks, and coding patterns that lead to them.

  • How to prevent leaks in practice.

  • AndroidViewModel vs ViewModel — differences and when to use which.

Coroutines

  • What is a coroutine, and why do we need it? Brief discussion of threads vs coroutines.

  • Ways of launching a coroutine: runBlocking, launch, async — when to use which.

  • Scopes: What is a CoroutineScope? What are viewModelScope and lifecycleScope? Within these, we discussed coroutine cancellation, lifecycle awareness, and job cancellation.

  • async and Deferred: What does deferred mean? When does suspension happen, and when does the deferred block actually start executing?

  • A few more conceptual questions around coroutines to close out.


suspend fun init() {

val val1 = async { /* ... */ }

val val2 = async { /* ... */ }

  

// initialize something

  

val1.await()

val2.await()

}

Round 2: DSA Round

Format: Offline (Adobe Office) · Platform: HackerRank live session

Introduction

The round started with brief introductions — myself and the interviewer — along with some small talk about weather and general well-being. I was then asked to take out my laptop, and the interviewer shared a HackerRank live session link.

Format

There were two DSA questions. I was asked to look at Problem 1 first and decide whether I wanted to attempt it or look at Problem 2 and start there. I looked at Problem 1 and decided to attempt it first.

The interviewer set an expectation upfront: brute force approaches would only be discussed, not coded, to save time. Once we arrived at the optimal solution, I could code it up.

Problem 1: Nice Array

Statement: A Nice Array is an array in which removing exactly one element makes the array strictly increasing. You are given a list of positive integers — find the number of elements that need to be removed to make the array a Nice Array.

  • I first discussed the brute force approach, followed by its time and space complexity.

  • We then discussed that we could do better, and I proposed the optimal solution.

  • I wrote pseudo-code on paper and did a dry run on the example input.

  • The interviewer was satisfied with the approach. We then discussed a few edge cases and follow-ups:

  • Duplicates — how would my approach change if duplicates were allowed (i.e., strictly increasing vs non-decreasing)?

  • Already sorted array — the trivial case.

I was then given a choice: code this problem now, or move to the next one and code later. I decided to move to the next question.

Problem 2: Shops on a Street

Statement: You are given a list of integers representing shops on a street. Each number is the amount I must spend at that shop before moving to the next. You are given n queries of the form [Sᵢ, Capᵢ], where Sᵢ is the starting shop and Capᵢ is the amount I have. For each query, return the farthest shop I can reach.

  • I initially proposed the brute force approach using linear search per query.

  • I then arrived at the optimal solution: cummulative sums + binary search per query.

  • The interviewer was okay with the approach and asked me to code either of the two problems.

Coding & Wrap-up

I chose to code Problem 2. A few test cases failed — I walked the interviewer through the edge cases where my solution was failing and how I would fix them, but we ran out of time.

Round 3 - System Design

Format: Offline (Adobe Office) · Duration: 1 hour

Introduction & Expectations

The round started with a basic introduction, after which the interviewer set expectations for the interview. He said he would throw very broad, open questions at me and we'd discuss around them. He expected a certain depth in each concept — once he found the depth he was looking for, we'd immediately move to the next topic. My goal should be to state the facts I know immediately, so he could extract as much information from me as possible.

Dependency Injection

  • Started with what is dependency injection and the need for it.

  • Began with the basic motivation for DI, then circled to the Android-specific need — activities and other components are instantiated by the system, not by constructor calls.

  • Discussed Dagger and Hilt — how Hilt simplifies things, whether we can use Dagger without Hilt, and what the challenges are.

  • Discussed scoping of objects — what "scope" means in the context of Hilt.

LLD Problem 1: Search Bar with Suggestions

Problem: Implement a search bar that provides suggestions, with the data sitting on the backend and search firing a network call.

Follow-up discussion:

  • Caching vs no caching - we steered towards caching.

  • Debouncing the search input.

  • Data sources and mediation between the two sources (local cache and backend).

  • Prefix search - and the data structures suited for it.

LLD Problem 2: Infinite Scroll

Problem: Implement an infinite scroll.

Follow-up discussion:

  • When to fetch the next page.

  • Handling dynamic data — e.g., new rows inserted into an already-fetched page.

  • Fetching approach — page numbers vs cursors.

  • Storage and mediation — how I would store the data and mediate it to the upper layers.

App Architecture & Performance

  • How I would layer/structure the app — what logic lives where.

  • Ensuring performance checks and good practices — e.g., network calls on the IO dispatcher.

  • Repository vs use cases — when to use what.

  • ViewModel and coroutines — what is viewModelScope, then what is a CoroutineScope. The interviewer expected depth around lifecycle management here; once I answered that, we moved to UI.

  • LazyColumn vs a normal Column — how performance is affected in each. I discussed recomposition, disposing of composables, and related behavior.

Wrap-up

The interview ended a bit earlier than expected. The interviewer said he was done and I could ask anything I wanted. I was a bit confused, since I expected more questions — and I told him so. He said, "let's keep going for a few more minutes," and we discussed some challenging work I've done in my career before ending the interview.

Round 4: Hiring Manager Round

Format: Offline (Adobe Office) · Duration: 1–1.5 hours

Introduction

This was the final round, with the hiring manager. The interview started with basic introductions — the interviewer introduced himself and asked me to introduce myself and walk through my career experience. During the walkthrough, he asked questions in between — less technical, more around how I approach problems in general and how I manage a team.

Cultural Fit Questions

Once I was done with my walkthrough, he said we'd do some basic cultural fit questions and then move to open discussion. These were standard hiring manager questions, such as:

  1. Why do you want to join Adobe?

  2. What's the most challenging thing you've done in your career?

  3. As a team lead, how do you ensure alignment when some team members are misaligned?

  4. Describe a scenario where you overcame a hurdle.

  5. Describe a scenario where you solved a really challenging task.

  6. Describe a scenario where you demonstrated teamwork.

  7. Describe a scenario where you demonstrated leadership spirit.

Overall there were 12–15 cultural fit questions along these lines.

Design Problem: Promo Processor

I was then given a problem statement to design a "Promo Processor" (my name for it — the interviewer just described the problem).

Context: Multiple promos/dialogs currently appear in the Acrobat Reader app — banners, dialogs, ads, feature promotions. Users complain a lot about this. The idea is to design a promotion processor infrastructure that handles when a promotion should be displayed. Its only job is to tell the UI layer when to display which promotion.

My approach:

  • Discussed the problem with the interviewer and listed down all the required features.

  • Discussed the high-level design in brief.

  • Moved into low-level design and discussed around that.

Wrap-up

This round ran over its allocated time. It ended with my questions about the org structure, the project, and when I would be staffed.

Comments (1)