Skip to content

refactor(platform-android)!: report changed permission ids, not a joined string - #3023

Merged
thymikee merged 3 commits into
mainfrom
refactor/settings-permission-changed-ids-2701
Sep 29, 2026
Merged

thymikee merged 3 commits into
mainfrom
refactor/settings-permission-changed-ids-2701

Conversation

@thymikee

@thymikee thymikee commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Summary

Android settings permission responses reported changed ids under two inconsistent shapes: a comma-joined permission string on named/pm targets, and a separate applied array on all. Every response path now reports permission as the requested target name and permissions: string[] as the ids actually mutated, in order. applied folds into permissions; the not-requested error detail uses the array too. Updates website/docs/docs/commands.md accordingly.

// deny location (multi-id fan-out)
{ permission: 'location', permissions: ['android.permission.ACCESS_FINE_LOCATION', 'android.permission.ACCESS_COARSE_LOCATION'], priorGrantState: 'granted' }

3 files touched. No public TS response type exists for this command (return is Record<string, unknown>), so no client-types change is needed; the repo has no CHANGELOG.md/changeset mechanism, so no changelog entry was added.

Closes #2701. Nominally stacked on refactor/settings-permission-typed-skip-2700 (#2700), but that branch's diff already merged as a212d9a55a (#3010) and its remote branch is gone, so this branch is rebased directly onto main and carries only the #2701 diff.

Validation

Tested at c55b03ba69.

  • pnpm vitest run packages/platform-android/src/__tests__/settings-permission.test.ts test/integration/provider-scenarios/android-lifecycle.test.ts: 44/44 passed, including a grant location coarse-only test, a pinned deny location revoke fan-out, and a provider scenario that asserts permission and permissions end to end.
  • pnpm check:affected --run: all runnable checks passed (one daemon-entrypoint timeout from host contention on the first run; the rerun passed).
  • Live, Android emulator (API 37), app org.telegram.messenger.web, settings permission grant location then deny location:
grant: "permission": "location", "permissions": ["android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"]
deny:  "permission": "location", "permissions": [same two ids], "priorGrantState": "granted", warnings: [2 relaunch warnings]

Review in cubic

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-29 09:52 UTC

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.88 MB 4.88 MB +184 B
Package (unpacked) 4.88 MB 4.88 MB +184 B
Package (download) 1.46 MB 1.46 MB +44 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 27.0 ms 27.0 ms -0.0 ms
CLI --help 80.4 ms 78.5 ms -1.8 ms

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread website/docs/docs/commands.md
Comment thread packages/platform-android/src/__tests__/settings-permission.test.ts
@thymikee

Copy link
Copy Markdown
Member Author

Reviewed at 47f6d36. Named grant responses do not include the fields that the docs now promise.

commands.md:764 says every Android response reports permission and permissions. But settings permission grant <named target> goes through grantAndroidPermission, which returns nothing (settings-permission.ts:434-455). For example, grant location on a coarse-only app grants only COARSE, but the client gets no permissions and cannot tell which ids changed. Please have grantAndroidPermission return the ids it applied, and build the response in one place in setAndroidPermission for grant and revoke. A grant location test on a coarse-only app can prove it. If that is too much for this PR, the smaller fix is to limit the docs sentence to deny, reset and all.

Not blocking: applied and the comma-joined permission were released in v0.21.8 to v0.21.16, so this is a breaking output change; a ! in the title or a BREAKING CHANGE footer would say so.

CI: Smoke Tests is still queued. No failures yet.

…ed string

permission still names the requested target; permissions: string[]
carries the ids each revoke/all response actually mutated, replacing
the comma-joined permission and the applied field. Error details use
the same array instead of a joined string.

Closes #2701
@thymikee
thymikee force-pushed the refactor/settings-permission-changed-ids-2701 branch from 47f6d36 to c55b03b Compare September 28, 2026 20:36
@thymikee thymikee changed the title refactor(platform-android): report changed permission ids, not a joined string refactor(platform-android)!: report changed permission ids, not a joined string Sep 28, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Pushed c55b03b (rebased on main).

  • Named grant now returns the ids it applied, and grant and revoke build the response in one helper. grant location on a coarse-only app reports just the COARSE id; there is a test for it.
  • The Android provider scenario now asserts permission and permissions for a grant end to end. The deny location test also pins both pm revoke calls (the cubic note).
  • Checked live on an emulator: grant and deny location both report both ids.
  • Marked the title as breaking, since applied and the joined permission string were released.

CI: waiting on the new run; I will treat only the iOS Smoke Tests flake as acceptable.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/platform-android/src/settings-permission.ts">

<violation number="1" location="packages/platform-android/src/settings-permission.ts:460">
P3: The newly added grant response is only asserted for `pm`-kind targets (location in the unit test, camera in the integration test). The `photos` and `notifications` grant branches also return a `{ permission, permissions }` response now — `[target.permission]` here and `[await setAndroidPhotoPermission(...)]` in the photos branch — and no test pins those. Add assertions on the returned `permission`/`permissions` for the existing `grant photos` and grant-notifications tests so the unified shape is actually covered for every kind.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

): Promise<string[]> {
if (target.kind === 'notifications') {
await setAndroidNotificationPermission(device, appPackage, 'grant', target, userArgs);
return [target.permission];

@cubic-dev-ai cubic-dev-ai Bot Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The newly added grant response is only asserted for pm-kind targets (location in the unit test, camera in the integration test). The photos and notifications grant branches also return a { permission, permissions } response now — [target.permission] here and [await setAndroidPhotoPermission(...)] in the photos branch — and no test pins those. Add assertions on the returned permission/permissions for the existing grant photos and grant-notifications tests so the unified shape is actually covered for every kind.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/platform-android/src/settings-permission.ts, line 460:

<comment>The newly added grant response is only asserted for `pm`-kind targets (location in the unit test, camera in the integration test). The `photos` and `notifications` grant branches also return a `{ permission, permissions }` response now — `[target.permission]` here and `[await setAndroidPhotoPermission(...)]` in the photos branch — and no test pins those. Add assertions on the returned `permission`/`permissions` for the existing `grant photos` and grant-notifications tests so the unified shape is actually covered for every kind.</comment>

<file context>
@@ -437,15 +454,18 @@ async function grantAndroidPermission(
+): Promise<string[]> {
   if (target.kind === 'notifications') {
     await setAndroidNotificationPermission(device, appPackage, 'grant', target, userArgs);
+    return [target.permission];
   } else if (target.kind === 'photos') {
-    await setAndroidPhotoPermission(device, appPackage, 'grant', userArgs);
</file context>
Fix with cubic

@thymikee

Copy link
Copy Markdown
Member Author

The PR is ready at c55b03b. The earlier findings from 47f6d36 are fixed.

Not blocking: android-lifecycle.test.ts grows from 1259 to 1261 lines, which trips the Coverage size ratchet, so please keep it at 1259 or fewer by moving the new permission assertions into a smaller test file or making the edit net-zero, with no baseline entry. The photos and notifications grant tests in settings-permission.test.ts could also assert permission and permissions, since those branches now return [id] (https://github.com/callstack/agent-device/blob/c55b03b/packages/platform-android/src/settings-permission.ts#L459-L462). You can take or leave these.

I did not run the tests. The 44/44 pass and the emulator output are author-reported. The live run used a Telegram package, not a coarse-only app, so only the unit test covers coarse-only behavior.

Coverage fails because of this diff, for the reason above. Smoke Tests fails at "restore fixture home after WebView lab" (simctl openurl timed out, code=60). This PR touches only Android permission code, so that looks like the cold-toolchain iOS flake. I judged this from the step name and the file overlap, not the full log. No conflicts.

Before merge, get android-lifecycle.test.ts to 1259 lines or fewer and re-run CI. Smoke Tests needs only a re-run.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 29, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Pushed 076bcde. The camera grant in the Android lifecycle scenario now shares its fixed fields, so the test file is back under its size limit (1257 lines). Both camera-grant assertions are still there.

@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready at 076bcde. The earlier review at c55b03b was clean, and the change since then is test-only formatting, so the code result is the same. All checks pass. I did not run the tests locally, and the file has only one camera-grant call, so I read the two assertions on that call as the "both" assertions.

Not blocking: the new docs line at https://github.com/callstack/agent-device/blob/076bcde/website/docs/docs/commands.md#L764 says permissions holds "the ids actually mutated", but for notifications the grant and revoke paths always return POST_NOTIFICATIONS, even when pm refuses it (API below 33, or the app did not declare it). You could say "the ids the target applied" instead, or return the id only when pm exits 0. Take it or leave it.

@thymikee
thymikee merged commit dbf113a into main Sep 29, 2026
21 checks passed
@thymikee
thymikee deleted the refactor/settings-permission-changed-ids-2701 branch September 29, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android settings permission response: one permissions list for changed ids, not permission: "a,b"

1 participant