My Adobe Interview Experience for Android MTS-2 (SDE-III Level) ~ Full Breakdown
#android
#adobe
#interview-experience
#backend-engineering
If you are prepping for an Android interview at Adobe, this one is for you. I recently gave the interview for the MTS-2 Android role and I want to share what happened, round by round, in plain simple words.
Quick intro: I have 2 years of experience and I currently work as an Android Engineer at a startup, at the SDE-III level. Result is still pending as I write this.
There were 4 rounds:
- Android Basics Deep Dive
- DSA Round
- System Design
- Hiring Manager Round
Let's get into it.
Round 1: Android Basics Deep Dive (1 hour, Online on MS Teams)
Started with a simple intro , my career so far, my open-source work and a few questions about my current team (size, structure, what my day looks like).
Singleton Pattern
He asked what is a singleton class and I wrote a basic one in Java.
class Database {
private static Database INSTANCE;
private Database() {}
static Database getInstance() {
if (INSTANCE == null) INSTANCE = new Database();
return INSTANCE;
}
}
Follow-up: is this thread-safe? It's not , two threads can both see INSTANCE as null at the same time and create two objects. We discussed how to fix this properly.
Then Kotlin , different ways to write a singleton:
objectdeclaration (simplest)- Java-style, manually
synchronizedblock
object Database
Good point that came up: synchronized is a JVM thing, so it won't work if you're writing shared code for Kotlin Multiplatform. You'd need platform-specific locking there.
Measuring App Performance
He asked how you'd measure if an app is performing well. We covered:
- Memory leaks
- UI jank
- ANR (main thread blocked for 5+ seconds)
- Crashes
- Slow UX from things like slow DB queries or heavy work on the wrong thread
I mentioned Crashlytics and Android Studio's App Inspection for catching these.
Memory Leaks
We went deeper here , what a leak actually is, common Android scenarios that cause them (Context leaks, holding Activity references too long, listeners never removed) and how to prevent them. Also asked: AndroidViewModel vs ViewModel , same thing, except AndroidViewModel also gives you access to Application context.
Coroutines
Big chunk of the round. What is a coroutine, why do we need it, how is it different from a thread. Then the different ways to launch one , runBlocking, launch, async and when to use each.
Then scopes , what CoroutineScope is and what viewModelScope / lifecycleScope actually do, which led into how cancellation works.
Then async and Deferred , when does the block inside async actually start running?
suspend fun init() {
val val1 = async { /* ... */ }
val val2 = async { /* ... */ }
// initialize something
val1.await()
val2.await()
}
Both val1 and val2 start immediately and you only wait for them once you call .await(). Classic question, so be ready to explain it clearly.
Where I could've done better: When explaining synchronized in KMP context, I fumbled a bit before landing on a clean explanation. I'd recommend rehearsing this one out loud beforehand , it's an easy topic to sound unsure about even if you know it.
Round 2: DSA Round (Offline at Adobe Office, on HackerRank)
In-person round, live coding on HackerRank. He gave me two problems and let me pick where to start. He also said upfront , brute force would only be discussed, not coded, to save time. Good sign if your interviewer says this too.
Problem 1: Nice Array
Problem: A "Nice Array" is one where removing exactly one element makes it strictly increasing. Given a list of positive integers, find how many elements need removing.
I explained brute force first (try removing each element, check if the rest is strictly increasing), then worked up to the optimal approach and dry-ran it on paper.
Follow-ups:
- What if duplicates are allowed , how does "strictly increasing" become "non-decreasing"?
- What about an already-sorted array (the trivial case)?
public int minRemovalsToMakeNice(int[] arr) {
int n = arr.length;
int badIndex = -1;
int count = 0;
for (int i = 1; i < n; i++) {
if (arr[i] <= arr[i - 1]) {
badIndex = i;
count++;
}
}
if (count == 0) return 0;
if (count > 1) return count;
if (isStrictlyIncreasingAfterRemoving(arr, badIndex - 1) ||
isStrictlyIncreasingAfterRemoving(arr, badIndex)) {
return 1;
}
return 2;
}
private boolean isStrictlyIncreasingAfterRemoving(int[] arr, int indexToSkip) {
int prev = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (i == indexToSkip) continue;
if (arr[i] <= prev) return false;
prev = arr[i];
}
return true;
}
Logic in short: find the break point where the array stops being strictly increasing. More than one break means one removal won't fix it. Exactly one break means try removing the element right before it or at it and check which one works.
Problem 2: Shops on a Street
Problem: A list of numbers where each number is the amount you must spend at that shop to move ahead. Given queries [Sᵢ, Capᵢ] (start shop, money available), find the farthest shop reachable for each query.
Brute force: linear search per query. Optimal: cumulative sums + binary search per query.
public int[] farthestShopReachable(int[] costs, int[][] queries) {
int n = costs.length;
long[] prefixSum = new long[n + 1];
for (int i = 0; i < n; i++) {
prefixSum[i + 1] = prefixSum[i] + costs[i];
}
int[] result = new int[queries.length];
for (int q = 0; q < queries.length; q++) {
int start = queries[q][0];
long cap = queries[q][1];
int low = start, high = n - 1, farthest = start;
while (low <= high) {
int mid = low + (high - low) / 2;
long spendNeeded = prefixSum[mid + 1] - prefixSum[start];
if (spendNeeded <= cap) {
farthest = mid;
low = mid + 1;
} else {
high = mid - 1;
}
}
result[q] = farthest;
}
return result;
}
I coded this one live and a couple of test cases failed. I walked the interviewer through where I thought the bug was, but we ran out of time before fixing it completely.
Mistake I made: I jumped into coding a bit too fast without re-checking my binary search boundary conditions on paper first. That's exactly where the bug was , an off-by-one in the low/high update. If I had dry-run the edit cases (start = last shop, cap = 0) before typing, I'd have probably caught it. Lesson: even under time pressure, spend 30 seconds walking through 1-2 edge cases before you start typing.
Round 3: System Design (Offline at Adobe Office, 1 hour)
The interviewer set clear expectations: broad open questions and once he got the depth he wanted on a topic, he'd move on. His advice , just say what I know quickly and clearly.
Dependency Injection
What is DI and why we need it, then Android-specific , since the system creates Activities and components (not you), how do you inject dependencies into them?
Follow-ups: Dagger vs Hilt (how Hilt simplifies things, can you use Dagger alone) and scoping in Hilt.
LLD 1: Search Bar with Suggestions
Backend-driven suggestions as the user types.
Follow-ups:
- Cache or no cache? (We leaned towards caching.)
- Debouncing the input.
- Which source to show first , cache or backend?
- Right data structure for prefix search (Trie).
LLD 2: Infinite Scroll
Follow-ups:
- When to trigger the next page fetch.
- Handling new rows added to an already-fetched page.
- Page numbers vs cursors.
- How to store and pass data up to the UI.
App Architecture & Performance
- How to layer the app.
- Network calls on the IO dispatcher, not main.
- Repository vs Use Cases , when you need which.
viewModelScopeandCoroutineScope, with real depth on lifecycle management.LazyColumnvsColumn, recomposition, disposal of composables.
The round ended a little early. The interviewer asked if I had questions and I told him honestly I expected more , he laughed and said "let's keep going a few more minutes," and we chatted about tough work challenges instead.
Where I slipped up: On the infinite scroll follow-up about new rows getting added mid-scroll, I gave a fairly generic answer (just "re-fetch and merge") without thinking through how that affects the user's current scroll position. The interviewer pushed on this and I only got to a solid answer after some back and forth. In hindsight, I should've thought about the UX side (not just the data side) before answering.
Round 4: Hiring Manager Round (Offline at Adobe Office, 1–1.5 hours)
Started with introductions and a walkthrough of my career, with the hiring manager asking questions about how I think and how I manage a team along the way.
Culture Fit Questions
About 12-15 questions in this style:
- Why do you want to join Adobe?
- Most challenging thing you've done in your career?
- How do you keep a team aligned when some members aren't on the same page?
- Time you overcame a big hurdle.
- Time you solved something really difficult.
- Time you showed real teamwork.
- Time you showed leadership.
Tip: keep 3-4 solid stories ready that you can reshape to fit different versions of these questions.
Design Problem: The "Promo Processor"
Context: In Acrobat Reader, too many promos (banners, dialogs, ads) show up at once and users complain. Task: design a system whose only job is deciding when to show which promotion, then tell the UI layer.
I listed the required features, sketched the high-level design, then went into low-level design details. The round ran over time, which felt like a good sign. Ended with me asking about team structure, the project and staffing timeline.
Mistake I made: During the culture-fit questions, my answer to "how do you handle a misaligned team member" was a bit too abstract at first , I spoke in general principles instead of a real example. The hiring manager gently nudged me with "can you give me a specific instance," and only then did I share an actual story. Lesson: lead with a concrete example first, then generalize if needed , not the other way around.
My Overall Takeaways
- Know your basics deeply. Singleton, memory leaks, coroutines , these are baseline expectations at this level and follow-ups test how deep you can go.
- Talk through edge cases before you type. My DSA bug came from skipping this step.
- For design rounds, expect a follow-up on every answer. Caching, data structures, edge cases , always coming.
- For hiring manager rounds, lead with real examples, not general principles.
- It's fine to be honest if something feels off in the interview , being upfront didn't hurt me.
That's my full Adobe Android MTS-2 interview experience. I'll update this once I hear back on the result. Hope it helps you walk in a bit more prepared than I did.
