Agent brief: app not staying foreground (AutoMobile CI)¶
Audience: IDE agents and app engineers debugging host app behavior when AutoMobile JUnit tests report odd failures in CI or locally.
Symptoms (often together):
launchAppreturns success, but the launcher (e.g. Nexus Launcher) stays focused.daemon.logshows the foreground package ascom.google.android.apps.nexuslauncher(or another launcher), not yourapplicationId.observecan still pass while the wrong screen is visible (valid snapshot ≠ your app’s UI).- Later steps (
tapOn,waitFor) fail because elements exist only in your app. failedStep.failureObservationin the plan result shows launcherpackageNameat failure time.
Goal: Decide whether the problem is your APK / activity lifecycle (crash, immediate finish, wrong component) vs test plan assertions that allow the launcher. Collect evidence the app team can act on.
What a narrow CI logcat already proves¶
Some pipelines only archive logcat filtered to activity / task lines (e.g. ActivityTaskManager). That is enough to see intents and transitions, and often enough to see CtrlProxy working.
It is usually not enough to answer: why did my process disappear or never hold focus?
If the saved logcat has no lines like:
FATAL EXCEPTIONAndroidRuntimeProcess … has diedSecurityException/IllegalStateExceptiontied to your package
…then you are not missing a hidden line inside that same file. You need wider logcat or dumpsys captured in the same time window as the failure (or reproduce locally with the same APK).
Evidence to collect (priority order)¶
New vs old file: adb logcat -c clears the device’s ring buffer, then you launch and adb logcat -d dumps a fresh capture from that session. That does not modify or append to an existing CI logcat artifact—you are generating new text to save or paste. For the same APK behavior as CI, use the same build (flavor, signing, env) and the same emulator/API level when possible.
Beyond logcat: steps 1–3 are pidof / dumpsys (not logcat). Keep them in the same bundle you share—they often explain focus/stack when logcat is still noisy.
If correlating with a CI failure: still attach daemon.log (or the CI line that points to it) and JUnit / Gradle failure output so the timeline matches; the adb block above is for device-side root cause.
Use the same application id your YAML plan uses (appId). Replace PACKAGE below (e.g. com.example.app).
1. Process still alive after launch¶
bash
adb wait-for-device
adb shell pidof PACKAGE
- Empty output: process is not running (crash, immediate
finish(), or never started correctly).
2. What window actually has focus¶
bash
adb shell dumpsys window | grep -E 'mCurrentFocus|mFocusedApp'
- If the line shows a launcher package instead of
PACKAGE, your app is not the focused window—even ifam start/launchAppappeared to succeed.
3. Activity stack (optional but high signal)¶
bash
adb shell dumpsys activity activities | head -n 200
Search the output for PACKAGE and the top Resumed / mResumedActivity section. This shows whether your activity resumed and what sits above it in the stack.
4. Broader logcat (this is the main gap vs narrow CI captures)¶
Clear, launch once, then dump errors:
bash
adb logcat -c
adb shell monkey -p PACKAGE -c android.intent.category.LAUNCHER 1
sleep 3
adb logcat -d '*:E' 'AndroidRuntime:E' 'ActivityManager:I' 'WindowManager:I' | tail -n 200
If your package has a known log tag, also run (replace YourTag):
bash
adb logcat -d | grep -E 'AndroidRuntime|FATAL|PACKAGE|YourTag' | tail -n 120
Look for: the first stack trace or fatal error mentioning your package after launch.
5. PID-scoped logcat (when the process exists briefly)¶
Right after launch, try:
bash
PID=$(adb shell pidof PACKAGE | tr -d '\r')
test -n "$PID" && adb logcat --pid="$PID" -d | tail -n 150
If pidof is empty, skip this and rely on step 4 (wide logcat).
After a fresh run: what you are looking for¶
There is no single canonical filename CI must produce. What matters is that you saved plain text for each command (upload as job artifacts, or paste into a ticket). Treat that bundle as one “evidence package.”
1. pidof output (step 1)
- Good for debugging: a numeric PID (process still alive a moment after launch).
- Smoking gun: empty → app is not running; pair with logcat for crash vs silent exit.
2. mCurrentFocus / mFocusedApp lines (step 2)
- Good: your PACKAGE appears on the focus line.
- Problem: launcher or another package → explains why AutoMobile still “sees” launcher UI even after launchApp.
3. Wide logcat (step 4, and step 5 if you had a PID)
Scan top-to-bottom for the first occurrence of any of:
FATAL EXCEPTION(especially with your package orAndroidRuntimebelow it)AndroidRuntime: Estack tracesProcess <your.package> has died(wording varies by API)SecurityException,IllegalArgumentException,IllegalStateExceptionmentioning your code
That block (a few dozen lines around the first hit) is usually the artifact you hand to the app team.
4. dumpsys activity excerpt (step 3)
Use when logcat is clean but focus is wrong: find mResumedActivity / Resumed and whether your ActivityRecord appears, finished, or sits under a dialog/overlay.
5. Still running AutoMobile tests
Keep daemon.log + JUnit/Gradle failure snippet from the same run so you know which plan step failed and what the daemon thought the foreground app was.
Bottom line: you are looking for actionable text: either a crash stack in logcat, or focus/stack proof that your activity never resumed or exited immediately—saved as files or logs you can link, not a specific proprietary “artifact type.”
How this maps to fixes¶
| Finding | Likely area |
|---|---|
FATAL EXCEPTION / AndroidRuntime for your package |
App bug (startup crash, missing dep, migration, etc.) |
SecurityException / permission denial |
Manifest, runtime permissions, or device policy |
pidof empty, no crash in logcat |
Immediate finish(), wrong launcher activity, or process name / user profile mismatch |
| Focus stays on launcher, app process alive | Overlay, dialog, or another activity on top—investigate stack (step 3) |
| Focus wrong, tests still “observe” | Harden the YAML (next section) |
Harden AutoMobile YAML (parallel track)¶
Treat launchApp success as start was attempted, not your UI is visible.
Immediately after launchApp, wait for something only your app can show (resource id including your package):
```yaml - tool: launchApp appId: PACKAGE label: Start app
- tool: observe label: Wait for app-specific chrome waitFor: elementId: “PACKAGE:id/your_main_view” timeout: 15000 ```
waitFor must include text or elementId (not timeout alone). See Writing Tests → observe.
Full AutoMobile / CI context¶
- CI app launch troubleshooting — CtrlProxy alignment, daemon flags,
daemon.log, emulator checks outside AutoMobile - CI daemon logs — capturing
daemon.logfrom CI
When sharing with an agent, attach: CI job excerpt, daemon.log, JUnit failure, and the artifacts from steps 1–4 above (plus step 5 when pidof returns a PID) from the same failing run or a local repro with the same APK.