Skip to content

fix(patrol): make Android UiAutomation accessibility flags configurable - #3216

Draft
Kendru98 wants to merge 1 commit into
masterfrom
claude/patrol-flag-defaults-025ec4
Draft

fix(patrol): make Android UiAutomation accessibility flags configurable#3216
Kendru98 wants to merge 1 commit into
masterfrom
claude/patrol-flag-defaults-025ec4

Conversation

@Kendru98

@Kendru98 Kendru98 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Make two Android UiAutomation accessibility flags configurable. Both opt-in, default = today's behavior.

Problem

Change

  • AndroidAutomatorConfig.dontSuppressAccessibilityServices (dart-define PATROL_ANDROID_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) → sets FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES via Configurator.
  • AndroidAutomatorConfig.retrieveInteractiveWindows (dart-define PATROL_ANDROID_RETRIEVE_INTERACTIVE_WINDOWS) → false clears the flag.
  • Flags flow config → ConfigureRequest contract → Automator.configure(); iOS ignores them.

Watch out

  • uiautomator re-adds the flag when serviceInfo.flags != mCachedServiceFlags or every SERVICE_FLAGS_TIMEOUT (2s), so a plain setServiceInfo() won't stick — mCachedServiceFlags/mLastServiceFlagsTime are pinned via reflection (guarded, degrades to default on failure).
  • FLAG_INCLUDE_NOT_IMPORTANT_VIEWS is preserved so normal selectors keep working.

Result

  • 14 Dart tests pass (4 new, covering config defaults + ConfigureRequest threading).
  • Native flag effect needs on-device verification (couldn't run an emulator here).

Closes #3201
Closes #3178

Copilot AI balanced review requested due to automatic review settings August 5, 2026 10:13
@github-actions github-actions Bot added the package: patrol Related to the patrol package (native automation, test bundling) label Aug 5, 2026
@Kendru98
Kendru98 force-pushed the claude/patrol-flag-defaults-025ec4 branch from abcff08 to 945539c Compare August 5, 2026 10:13
Both flags are opt-in and default to today's behavior.

#3201: Patrol acquired UiAutomation with flags=0, so the platform suppressed
every third-party AccessibilityService for the whole session. Add
AndroidAutomatorConfig.dontSuppressAccessibilityServices (dart-define
PATROL_ANDROID_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); when set, Patrol acquires
it with FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES via Configurator so other
services keep running.

#3178: uiautomator 2.3.0's UiDevice.getUiAutomation() force-enables
FLAG_RETRIEVE_INTERACTIVE_WINDOWS, which stops some WebViews (e.g. Plaid Link)
from ever populating their accessibility tree, breaking $.native selectors. Add
AndroidAutomatorConfig.retrieveInteractiveWindows (dart-define
PATROL_ANDROID_RETRIEVE_INTERACTIVE_WINDOWS); set it to false to clear the flag.
uiautomator re-adds it whenever serviceInfo.flags != mCachedServiceFlags or
every SERVICE_FLAGS_TIMEOUT (2s), so the private mCachedServiceFlags /
mLastServiceFlagsTime cache is pinned via reflection; FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
is preserved so normal selectors keep working.

Flags flow from AndroidAutomatorConfig through the ConfigureRequest contract to
Automator.configure() on Android; iOS ignores them.
@Kendru98
Kendru98 force-pushed the claude/patrol-flag-defaults-025ec4 branch from 945539c to a072a2e Compare August 5, 2026 10:15

Copilot AI 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.

Pull request overview

Adds configurable Android UiAutomation accessibility flags, addressing third-party accessibility-service suppression and WebView selector failures.

Changes:

  • Adds Android configuration fields and Dart defines.
  • Threads flags through cross-platform contracts.
  • Applies and pins native Android accessibility flags.

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
schema.dart Extends the configure contract.
packages/patrol/test/android_automator_config_test.dart Tests defaults and request forwarding.
packages/patrol/lib/src/platform/platform_automator.dart Exposes platform-level options.
packages/patrol/lib/src/platform/mobile/mobile_automator_native.dart Adds extensible configure requests.
packages/patrol/lib/src/platform/contracts/contracts.g.dart Serializes new fields.
packages/patrol/lib/src/platform/contracts/contracts.dart Defines new contract fields.
packages/patrol/lib/src/platform/android/android_automator_native.dart Forwards Android configuration.
packages/patrol/lib/src/platform/android/android_automator_config.dart Defines flags and Dart defaults.
packages/patrol/darwin/patrol/Sources/PatrolImpl/AutomatorServer/Contracts.swift Keeps Darwin contract compatible.
packages/patrol/CHANGELOG.md Documents the options.
packages/patrol/android/src/main/kotlin/pl/leancode/patrol/contracts/Contracts.kt Extends Android contracts.
packages/patrol/android/src/main/kotlin/pl/leancode/patrol/AutomatorServer.kt Passes flags to the automator.
packages/patrol/android/src/main/kotlin/pl/leancode/patrol/Automator.kt Applies Android accessibility flags.
packages/patrol_devtools_extension/lib/api/contracts.g.dart Updates DevTools serialization.
packages/patrol_devtools_extension/lib/api/contracts.dart Updates DevTools contracts.
Files not reviewed (2)
  • packages/patrol/lib/src/platform/contracts/contracts.g.dart: Generated file
  • packages/patrol_devtools_extension/lib/api/contracts.g.dart: Generated file
Suppressed comments (1)

packages/patrol/android/src/main/kotlin/pl/leancode/patrol/Automator.kt:128

  • This option is also one-way: once a test sets it to false, clearRetrieveInteractiveWindowsFlag() removes the bit and pins mLastServiceFlagsTime to Long.MAX_VALUE; a later test requesting true skips this block, so uiautomator never restores its default flag. Handle the true transition by restoring the service flag and unpinning/synchronizing the UiDevice cache.
        if (!retrieveInteractiveWindows) {
            clearRetrieveInteractiveWindowsFlag()
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// UiDevice.getUiAutomation() forwards Configurator.uiAutomationFlags to
// Instrumentation.getUiAutomation(flags), so setting it here is enough for
// uiautomator's own queries.
configurator.uiAutomationFlags = UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES
Comment on lines +121 to +123
if (dontSuppressAccessibilityServices) {
configureDontSuppressAccessibilityServices()
}
@Kendru98
Kendru98 marked this pull request as draft August 5, 2026 10:58
// Instrumentation.getUiAutomation(flags) exists only on API 24+. Below that,
// the flags-based opt-ins are unavailable and Configurator.uiAutomationFlags
// stays at its default (0), so the no-arg overload is equivalent.
private fun uiAutomationForConfiguredFlags(): UiAutomation {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this method used anywhere else than in the method above? Seems redundant

keyboardBehavior = keyboardBehavior ?? KeyboardBehavior.showAndDismiss,
dontSuppressAccessibilityServices =
dontSuppressAccessibilityServices ??
const bool.fromEnvironment(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No default value?

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

Labels

package: patrol Related to the patrol package (native automation, test bundling)

Projects

None yet

3 participants