Skip to content

Android: ColorOS blocks the test-only snapshot helper as a "PC install attack" (-99), removing all snapshot-based commands #2364

Description

@AliceLJY

Summary

On ColorOS (OPPO), the bundled Android snapshot helper cannot be installed. The device's package installer classifies the install as a "PC install attack" and fails the session with vendor code -99, so every snapshot-dependent command is unusable on these devices.

This is not a blanket adb-install restriction: normal (non-test-only) APKs install over the same adb connection without any prompt. The block is specific to APKs carrying android:testOnly="true", which the snapshot helper does.

Filing this because #1284 / #1285 deliberately chose hard-fail over the stock-UIAutomator fallback. That decision is sound, but it means an OEM that blocks test-only packages removes the entire Android capture surface with no supported escape hatch.

Environment

agent-device 0.20.10 (global npm install)
Host macOS 27.0, Node 22+
Device OPPO Find N6 (PLP110), ColorOS, targetSdk=36, physical device over USB
adb 1.0.41 / 37.0.1

Screen was on and unlocked throughout. USB debugging authorized (adb devices reports device, not unauthorized).

Reproduction

$ agent-device snapshot -i --json
Android snapshot helper failed: Failed to install Android snapshot helper:
failed to install .../agent-device-android-snapshot-helper-0.20.10.apk:
Failure [INSTALL_FAILED_TEST_ONLY]

Installing the same artifact by hand reproduces it and shows the vendor code:

$ adb install -r  <helper.apk>     # no -t
Failure [INSTALL_FAILED_TEST_ONLY]

$ adb install -r -t <helper.apk>   # with -t
Failure [-99]

$ adb push <helper.apk> /data/local/tmp/ && adb shell pm install -r -t /data/local/tmp/helper.apk
Failure [-99]

Root cause (logcat)

E OplusCustomizePackageManagerService: getAdbInstallUninstallDisabled start
D PackageManager: send package verification broadcast
D PackageManager: installStage allowInterceptAdbInstallInInstallStage pkg:com.callstack.agentdevice.snapshothelper
I PackageInstaller: PC install attack detected!com.callstack.agentdevice.snapshothelper
D PackageInstallerSession: Marking session as failed: -99
D PackageInstallerSessionExtImpl: uploadInstallFailInfos:{code=20010,
   initiatingPackageName=com.android.shell, targetSdk=36,
   app_pkg=com.callstack.agentdevice.snapshothelper, statusCode=-99}

-99 is not an AOSP PackageManager.INSTALL_FAILED_* constant; it comes from OPPO's interception layer (OplusCustomizePackageManagerService, allowInterceptAdbInstallInInstallStage).

What I ruled out

Hypothesis Test Result
Corrupt/truncated APK unzip -t on the bundled artifact Passes, no errors
Screen locked dumpsys window during install mScreenOn=true, mScreenLocked=false
AOSP adb-install verification Set verifier_verify_adb_installs 1 → 0, retry Still -99 (restored to 1 afterwards)
adb installs blocked wholesale Pulled an already-installed, release-signed app off the device and reinstalled it with adb install -r Success

That last row is the decisive one: the same adb channel installs a normal APK fine. Only the testOnly flag triggers the vendor block.

What still works without the helper

Verified on the same device with a session open: open / close, install / reinstall, screenshot (produced a 1140x2616 PNG), logs, apps. Only snapshot and everything built on it (click, fill, find, wait, diff) are unavailable.

Suggestions

  1. Document it. A line in the Android installation docs — "some OEM builds (ColorOS observed) reject test-only packages from adb; the snapshot helper cannot be installed on those devices" — would save the diagnostic time. The current hint from fix(android): actionable error when the snapshot helper is unavailable (#1284) #1285 is already good at saying what failed; naming this specific OEM class would say why.
  2. Consider an opt-in non-test-only helper build. If the helper did not set android:testOnly="true", it would install on these devices. I understand the flag is protective (it keeps the helper off Play and out of normal install flows), so this would need to be an explicit, clearly-labelled variant rather than the default.
  3. Consider an env var for a user-supplied helper artifact. adbProvider.snapshotHelperArtifact already exists for cloud providers; exposing an equivalent for local runs would let affected users supply a locally-repackaged helper without patching node_modules. I checked the AGENT_DEVICE_* surface and did not find one.

Happy to test any of these on the device — I have it available.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions