Skip to content

fix(android): remove Play-restricted permissions#39660

Merged
obviyus merged 6 commits intomainfrom
fix/android-play-restricted-permissions
Mar 8, 2026
Merged

fix(android): remove Play-restricted permissions#39660
obviyus merged 6 commits intomainfrom
fix/android-play-restricted-permissions

Conversation

@obviyus
Copy link
Contributor

@obviyus obviyus commented Mar 8, 2026

Summary

  • Problem: The Android app still declared Google Play restricted permissions / foreground service types (ACCESS_BACKGROUND_LOCATION, REQUEST_INSTALL_PACKAGES, FOREGROUND_SERVICE_MICROPHONE, FOREGROUND_SERVICE_MEDIA_PROJECTION) that trigger extra review and block Play release.
  • Why it matters: Play-distributed Android builds cannot ship the self-update install flow, and the current Android UX/runtime no longer justifies background location, microphone FGS, or media-projection FGS.
  • What changed: Removed Android self-update (app.update), cut Android location to foreground-only, removed Android screen.record, made voice mic sessions foreground-only, reduced the Android foreground service to dataSync only, updated docs/tests/runtime/UI, and bumped Android versionCode for a fresh Play upload.
  • What did NOT change (scope boundary): FOREGROUND_SERVICE_DATA_SYNC remains for the visible gateway connection foreground service, Android photo access (READ_MEDIA_IMAGES) remains unchanged, and non-Android node platforms were not refactored here.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #

User-visible / Behavior Changes

  • Android no longer advertises or supports app.update.
  • Android location now works only while the app is open; the Always mode is removed.
  • Android no longer advertises or supports screen.record.
  • Android voice mic capture now stops when the app leaves the foreground or the user leaves the Voice tab.
  • Play release manifests no longer include ACCESS_BACKGROUND_LOCATION, REQUEST_INSTALL_PACKAGES, FOREGROUND_SERVICE_MICROPHONE, or FOREGROUND_SERVICE_MEDIA_PROJECTION.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) Yes
  • Data access scope changed? (Yes/No) Yes
  • If any Yes, explain risk + mitigation:
    Removed Android command/capability surface (app.update, screen.record) and reduced Android runtime access from background to foreground-only for location and mic capture. Risk is intentional feature loss on Android; mitigation is that runtime, manifests, UI copy, docs, and advertised command lists were all updated together to match the narrower Play-safe scope.

Repro + Verification

Environment

  • OS: macOS host
  • Runtime/container: Android Gradle app module + repo TypeScript checks
  • Model/provider: n/a
  • Integration/channel (if any): Android node
  • Relevant config (redacted): none

Steps

  1. Build Android Kotlin sources and targeted Android unit tests.
  2. Regenerate the packaged release manifest and build a fresh release AAB.
  3. Inspect the packaged manifest / built AAB for removed Play-restricted permissions and foreground service types.

Expected

  • Android builds cleanly.
  • Targeted unit tests pass.
  • Release manifest / AAB contain FOREGROUND_SERVICE_DATA_SYNC only, and no ACCESS_BACKGROUND_LOCATION, REQUEST_INSTALL_PACKAGES, FOREGROUND_SERVICE_MICROPHONE, or FOREGROUND_SERVICE_MEDIA_PROJECTION.

Actual

  • Matches expected.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: ./gradlew :app:compileDebugKotlin; ./gradlew :app:testDebugUnitTest --tests ai.openclaw.app.node.DeviceHandlerTest --tests ai.openclaw.app.node.InvokeCommandRegistryTest --tests ai.openclaw.app.protocol.OpenClawProtocolConstantsTest; ./gradlew :app:processReleaseManifestForPackage --rerun-tasks; ./gradlew :app:bundleRelease; pnpm tsgo; direct scan of the built app-release.aab manifest payload.
  • Edge cases checked: packaged release manifest and final AAB on disk, not just source manifest; Android command/capability registry no longer exposes app.update or screen.record; app backgrounding now stops active mic capture; rebuilt AAB uses a fresh Android versionCode (202603081).
  • What you did not verify: live Play Console declaration flow or manual Android device recording for the remaining dataSync review.

Compatibility / Migration

  • Backward compatible? (Yes/No) No
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) Yes
  • If yes, exact upgrade steps:
    Upload a new Play build from this branch. Android users on this build lose background location.get, Android self-update, Android screen.record, and background mic capture; no operator-side config migration is required.

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert commits 53e0d367a, 87289bfe7, fd3d7d4f6, and 7259abb7a.
  • Files/config to restore: Android manifest, Android node command registry/dispatcher/runtime, deleted self-update and screen-record handler files, onboarding/settings copy, and Android Gradle version code.
  • Known bad symptoms reviewers should watch for: Android node still advertising app.update or screen.record; packaged release manifest or AAB still containing any removed restricted permission/FGS type; voice mic remaining active after app backgrounding.

Risks and Mitigations

  • Risk: Existing Android users lose capabilities they may rely on (app.update, screen.record, background location, background mic capture).
    • Mitigation: Scope reduction is intentional for Play compliance, and runtime/UI/docs/command advertisement now agree on the reduced Android surface.
  • Risk: Play may still scrutinize the remaining FOREGROUND_SERVICE_DATA_SYNC declaration for the long-lived gateway connection service.
    • Mitigation: This PR narrows the Android foreground service to dataSync only; any further policy cut can now focus on that single remaining declaration.

@openclaw-barnacle openclaw-barnacle bot added docs Improvements or additions to documentation app: android App: android gateway Gateway runtime size: L maintainer Maintainer-authored PR labels Mar 8, 2026
@obviyus obviyus self-assigned this Mar 8, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 8, 2026

Greptile Summary

This PR removes two Play-restricted Android permissions (ACCESS_BACKGROUND_LOCATION and REQUEST_INSTALL_PACKAGES) along with all supporting code — the self-update handler (AppUpdateHandler), its install receiver, and the Always location mode — to unblock Google Play distribution. The change is internally consistent: the manifest, runtime, command registry, dispatcher, UI (onboarding + settings), unit tests, live integration test, and docs all agree on the reduced capability surface.

Key changes:

  • Manifest: ACCESS_BACKGROUND_LOCATION and REQUEST_INSTALL_PACKAGES removed; InstallResultReceiver receiver declaration dropped.
  • LocationMode: Always enum entry removed; fromRawValue silently maps the legacy stored string "always" to WhileUsing for backwards compatibility.
  • LocationHandler: background-location logic simplified to a single !isForeground() guard; locationMode lambda parameter removed.
  • AppUpdateHandler / InstallResultReceiver: files deleted; dispatcher, registry, and protocol constants updated accordingly.
  • UI: Settings and onboarding no longer show the Always radio button or the "Install App Updates" toggle.
  • Tests & docs: all references to app.update, backgroundLocation, and Always mode removed or updated.

Confidence Score: 4/5

  • Safe to merge — the scope reduction is intentional, well-scoped, and consistent across all layers.
  • All changes are internally consistent across manifest, runtime, UI, tests, and docs. The only non-critical concern is that LocationMode.fromRawValue("always") returns WhileUsing without persisting the mapped value back to storage, so users who had Always stored will silently get WhileUsing at runtime but their raw preference remains "always" indefinitely. This is a minor data-cleanliness issue rather than a functional bug. No logic errors, no security regressions, and both restricted permissions are confirmed removed.
  • apps/android/app/src/main/java/ai/openclaw/app/LocationMode.kt — the "always" migration shim does not persist the new value to storage.

Last reviewed commit: 87289bf

@obviyus obviyus force-pushed the fix/android-play-restricted-permissions branch from 79a04e2 to 6c04088 Compare March 8, 2026 10:55
@obviyus obviyus merged commit eb0758e into main Mar 8, 2026
6 checks passed
@obviyus obviyus deleted the fix/android-play-restricted-permissions branch March 8, 2026 10:55
@obviyus
Copy link
Contributor Author

obviyus commented Mar 8, 2026

Landed via temp rebase onto main.

  • Gate: ./gradlew :app:compileDebugKotlin
  • Gate: ./gradlew :app:testDebugUnitTest --tests ai.openclaw.app.SecurePrefsTest --tests ai.openclaw.app.node.DeviceHandlerTest --tests ai.openclaw.app.node.InvokeCommandRegistryTest --tests ai.openclaw.app.protocol.OpenClawProtocolConstantsTest
  • Source head: 6c04088
  • Landed on main: eb0758e

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

Labels

app: android App: android docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant