Conversation
After two denials (or one "Don't ask again" before Android 11) the platform sets USER_FIXED and requestPermissions() answers denied with no dialog. The Manage... dialog showed that exactly like a permission never requested, and the only way back was Clear data, which also wipes the login and the database. The permission parser now keeps USER_SET and USER_FIXED. Manage... labels each denied row as "will ask" or "won't ask again", and right-click offers Ask again, which runs pm clear-permission-flags and trusts only a dumpsys read-back, since pm sets no exit status. The Home summary counts them and the diagnose permissions section lists them. Also stops the grant/revoke balloon printing ListItem's toString, and ignores dialog clicks below the last row, which used to toggle it. Refs #146 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The existing button asks for five permissions at once, which makes it hard to deny one twice and see the system stop prompting. The new button asks for CAMERA alone and prints how fast the answer came back, so an instant denial with no dialog is visible on the device. Refs #146 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Release notes come from CHANGELOG.md, and agents reading docs/MCP.md need to know the diagnose permissions section can carry wontAskAgain. Refs #146 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review found the dialog's labels and right-click menu were a snapshot while the checkbox was live: a won't-ask-again row ticked to grant still said "won't ask again" and still offered Ask again, which then reported success for a granted permission. Labels now follow the box, the menu only appears on unticked rows, and a successful Ask again updates its row in place through a success flag on resetPermissionPrompt. The reset verdict also refuses a granted permission, and names USER_SET when that is the flag left behind. The parser now stops after the first runtime-permissions block, so a permission only a work profile holds is not listed, and the diagnose section counts won't-ask-again names past its cap as moreDenied does. Refs #146 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
See when a permission won't be asked again, and reset it without clearing data. After two denials on Android 11+, or "Don't ask again" on older versions, Android sets
USER_FIXED. From then onrequestPermissions()returns denied immediately and shows no dialog. Until now, Home › Permissions › Manage… showed that the same way as any other unticked permission, and the only way out was Clear data, which wipes login, prefs and databases.This PR:
pm clear-permission-flags --user 0 <pkg> <perm> user-set user-fixed, then readsdumpsys packageback. Success is reported only when the flags are actually gone.pmsets no exit status, so its output is never treated as proof. The row updates in place after a successful reset.3 granted / 2 denied (1 won't ask again).android_diagnose_current_screenadds an optionalwontAskAgainarray, plusmoreWontAskAgainpast 12, to itspermissionssection. The key is absent when nothing is flagged, so existing consumers see identical JSON.GetApplicationPermission) now keepsUSER_SET/USER_FIXED, matching whole tokens soUSER_SENSITIVE_WHEN_DENIEDdoes not count. It reads only the first user's runtime block.ListItem(name=…, isSelected=…). It now prints the permission name.rationale=and how fast the answer came back, so you can watch the whole deny-twice → reset → prompt-returns cycle.No new
SpockAction, tool-window control or MCP tool. Tool counts are unchanged.Refs #146. This is a slice: the remaining piece is an MCP reset tool, which needs a decision on
SAFE_ACTIONvsDESTRUCTIVE.How it was verified
Run from the branch head
ea184bc:./gradlew detekt: pass, with no new suppressions./gradlew test: pass. 1453 tests, 0 failures, 9 skipped (the existing device/launcher-dependentMcpSmokeTest/McpBridgeServerTestcases).ToolSafetyTestandMcpSmokeTestare unchanged../gradlew buildPlugin: passcd sample && ./gradlew assembleDebug: pass (atd48659b; the later commit touches no sample files)New unit tests cover:
flags=, granted+fixed, a second user's block ignored)USER_SETleft, unknownpmcommand, not a runtime permissionpmcommand plus the read-back against a mockedIDevicePermissionSummary.describe()wontAskAgain/moreWontAskAgainkeysUnproven: needs
runIdeand/or a physical device or emulator.pm clear-permission-flagsdoes on API 29 and below, including the exact "Unknown command" wording. The plugin should report a refusal there; this is unit-tested only.Review notes
Two independent reviews (plugin invariants, and Kotlin) found no blocking issues. The should-fix items were fixed in
ea184bc:USER_SETremained.wontAskAgainwas truncated with no count of how many were cut.Still open (nits / known limits):
CheckBoxDialogis shared with the action-settings dialog andSpockActionsPopup. In all three, a right-click no longer toggles a row, and a click in the empty space below the list no longer toggles the last row. These changes are intended; smoke-test both other dialogs inrunIde.USER_SET("denied — will ask"). There it clears the denied-once state before a second denial. Restrict it to won't-ask-again rows if that is confusing.USER_FIXED.--user 0is hard-coded in both the parser and the reset (single-user assumption, consistent with the rest of the plugin).handelSelectiontypo inCheckBoxDialog, and a double blank line.CHANGELOG.md[Unreleased]and one line ofdocs/MCP.md.Produced unattended by the SpockAdb daily agent team (planner → builder → two reviewers). It needs a human read and a device run before merge.
🤖 Generated with Claude Code