also looking at this
fix(mobile): preserve native editing, navigation, and durable media requests
#369
36 files
+864
-185
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -160,9 +160,12 @@ export async function createAndroidEmulator(options: AndroidEmulatorOptions): Pr | ||
| 160 | 160 | // modifying device setup or relaxing native acceptance. |
| 161 | 161 | const home = await run([adb, '-s', serial, 'shell', 'cmd', 'package', 'resolve-activity', '--brief', '-a', 'android.intent.action.MAIN', '-c', 'android.intent.category.HOME'], undefined, probeTimeout(), true) |
| 162 | 162 | const homeActivity = home.stdout.trim().split(/\r?\n/).at(-1) ?? '' |
| 163 | const temporaryHome = homeActivity.startsWith('com.android.sdksetup/') | |
| 164 | || /^com\.android\.settings\/(?:\.|com\.android\.settings\.)FallbackHome$/.test(homeActivity) | |
| 165 | || /^android\/.*(?:Resolver|Chooser)Activity$/.test(homeActivity) | |
| 163 | 166 | booted = settings.code === 0 && packages.code === 0 && systemUi.code === 0 && events.code === 0 |
| 164 | 167 | && /^package:\/\S+/m.test(packages.stdout) && /^\d+(?:\s+\d+)*$/.test(systemUi.stdout.trim()) |
| 165 | && home.code === 0 && /^[\w.]+\/[\w.$]+$/.test(homeActivity) && !homeActivity.startsWith('com.android.sdksetup/') | |
| 168 | && home.code === 0 && /^[\w.]+\/[\w.$]+$/.test(homeActivity) && !temporaryHome | |
| 166 | 169 | } |
| 167 | 170 | } |
| 168 | 171 | const checkedAt = Date.now() |
| @@ -5,7 +5,7 @@ import { join } from 'node:path' | ||
| 5 | 5 | import { createAndroidEmulator } from '../../../android/src/emulator' |
| 6 | 6 | import type { AndroidEmulatorOptions } from '../../../android/src/emulator' |
| 7 | 7 | |
| 8 | function fixture(hardware: boolean, delayedSettings = false, delayedEvents = false, delayedHome = false): { root: string, options: AndroidEmulatorOptions } { | |
| 8 | function fixture(hardware: boolean, delayedSettings = false, delayedEvents = false, delayedHome = false, bootstrapHome = 'com.android.sdksetup/.DefaultActivity'): { root: string, options: AndroidEmulatorOptions } { | |
| 9 | 9 | const root = mkdtempSync(join(tmpdir(), 'craft emulator fixture ')) |
| 10 | 10 | const sdk = join(root, 'managed sdk') |
| 11 | 11 | for (const directory of ['bin', 'platform-tools', 'emulator']) mkdirSync(join(sdk, directory), { recursive: true }) |
| @@ -33,7 +33,7 @@ else | ||
| 33 | 33 | *'cmd package resolve-activity --brief -a android.intent.action.MAIN -c android.intent.category.HOME') |
| 34 | 34 | if [ '${delayedHome ? 'yes' : 'no'}' = yes ] && [ ! -f "$ANDROID_HOME/home-ready" ]; then |
| 35 | 35 | touch "$ANDROID_HOME/home-ready" |
| 36 | printf 'com.android.sdksetup/.DefaultActivity\\n' | |
| 36 | printf '${bootstrapHome}\\n' | |
| 37 | 37 | else |
| 38 | 38 | printf 'com.android.launcher3/.Launcher\\n' |
| 39 | 39 | fi ;; |
| @@ -135,6 +135,18 @@ test('boot completion waits for the automatic SDK setup activity to release HOME | ||
| 135 | 135 | finally { await session?.dispose(); rmSync(root, { recursive: true, force: true }) } |
| 136 | 136 | }, 10_000) |
| 137 | 137 | |
| 138 | test.each(['com.android.settings/.FallbackHome', 'android/com.android.internal.app.ResolverActivity'])('boot readiness rejects the temporary HOME destination %s', async (bootstrapHome) => { | |
| 139 | const { root, options } = fixture(true, false, false, true, bootstrapHome) | |
| 140 | let session: Awaited<ReturnType<typeof createAndroidEmulator>> | undefined | |
| 141 | try { | |
| 142 | session = await createAndroidEmulator(options) | |
| 143 | const trace = readFileSync(join(options.artifactsDirectory, 'device-commands.jsonl'), 'utf8').trim().split('\n').map(line => JSON.parse(line)) | |
| 144 | const home = trace.filter(entry => entry.args.includes('resolve-activity')) | |
| 145 | expect(home.map(entry => entry.stdout.trim())).toEqual([bootstrapHome, 'com.android.launcher3/.Launcher']) | |
| 146 | } | |
| 147 | finally { await session?.dispose(); rmSync(root, { recursive: true, force: true }) } | |
| 148 | }, 10_000) | |
| 149 | ||
| 138 | 150 | test('the SDK process fixture records hardware mode and reaps only its owned process', async () => { |
| 139 | 151 | const { root, options } = fixture(true) |
| 140 | 152 | options.bootTimeoutMs = 42_000 |