Fix for dynamic properties persisting between service restarts
NO_IFTTT=change adds IFTTT
Bug: 312386990
Test: atest AccessibilityServiceInfoTest
Flag: aconfig com.android.server.accessibility.cache_a11y_service_infos_for_restarting
Change-Id: I6b7d669629fdf066a3e199fac025c155dffabdd3
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index fc342fa..8bb2857 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -647,11 +647,44 @@
private int mObservedMotionEventSources = 0;
+ // Default values for each dynamic property
+ // LINT.IfChange(dynamic_property_defaults)
+ private final DynamicPropertyDefaults mDynamicPropertyDefaults;
+
+ private static class DynamicPropertyDefaults {
+ private final int mEventTypesDefault;
+ private final List<String> mPackageNamesDefault;
+ private final int mFeedbackTypeDefault;
+ private final long mNotificationTimeoutDefault;
+ private final int mFlagsDefault;
+ private final int mNonInteractiveUiTimeoutDefault;
+ private final int mInteractiveUiTimeoutDefault;
+ private final int mMotionEventSourcesDefault;
+ private final int mObservedMotionEventSourcesDefault;
+
+ DynamicPropertyDefaults(AccessibilityServiceInfo info) {
+ mEventTypesDefault = info.eventTypes;
+ if (info.packageNames != null) {
+ mPackageNamesDefault = List.of(info.packageNames);
+ } else {
+ mPackageNamesDefault = null;
+ }
+ mFeedbackTypeDefault = info.feedbackType;
+ mNotificationTimeoutDefault = info.notificationTimeout;
+ mNonInteractiveUiTimeoutDefault = info.mNonInteractiveUiTimeout;
+ mInteractiveUiTimeoutDefault = info.mInteractiveUiTimeout;
+ mFlagsDefault = info.flags;
+ mMotionEventSourcesDefault = info.mMotionEventSources;
+ mObservedMotionEventSourcesDefault = info.mObservedMotionEventSources;
+ }
+ }
+ // LINT.ThenChange(:dynamic_property_reset)
+
/**
* Creates a new instance.
*/
public AccessibilityServiceInfo() {
- /* do nothing */
+ mDynamicPropertyDefaults = new DynamicPropertyDefaults(this);
}
/**
@@ -758,7 +791,7 @@
}
}
peekedValue = asAttributes.peekValue(
- com.android.internal.R.styleable.AccessibilityService_summary);
+ com.android.internal.R.styleable.AccessibilityService_summary);
if (peekedValue != null) {
mSummaryResId = peekedValue.resourceId;
CharSequence nonLocalizedSummary = peekedValue.coerceToString();
@@ -793,10 +826,38 @@
if (parser != null) {
parser.close();
}
+
+ mDynamicPropertyDefaults = new DynamicPropertyDefaults(this);
}
}
/**
+ * Resets all dynamically configurable properties to their default values.
+ *
+ * @hide
+ */
+ // LINT.IfChange(dynamic_property_reset)
+ public void resetDynamicallyConfigurableProperties() {
+ eventTypes = mDynamicPropertyDefaults.mEventTypesDefault;
+ if (mDynamicPropertyDefaults.mPackageNamesDefault == null) {
+ packageNames = null;
+ } else {
+ packageNames = mDynamicPropertyDefaults.mPackageNamesDefault.toArray(new String[0]);
+ }
+ feedbackType = mDynamicPropertyDefaults.mFeedbackTypeDefault;
+ notificationTimeout = mDynamicPropertyDefaults.mNotificationTimeoutDefault;
+ mNonInteractiveUiTimeout = mDynamicPropertyDefaults.mNonInteractiveUiTimeoutDefault;
+ mInteractiveUiTimeout = mDynamicPropertyDefaults.mInteractiveUiTimeoutDefault;
+ flags = mDynamicPropertyDefaults.mFlagsDefault;
+ mMotionEventSources = mDynamicPropertyDefaults.mMotionEventSourcesDefault;
+ if (Flags.motionEventObserving()) {
+ mObservedMotionEventSources = mDynamicPropertyDefaults
+ .mObservedMotionEventSourcesDefault;
+ }
+ }
+ // LINT.ThenChange(:dynamic_property_update)
+
+ /**
* Updates the properties that an AccessibilityService can change dynamically.
* <p>
* Note: A11y services targeting APIs > Q, it cannot update flagRequestAccessibilityButton
@@ -808,6 +869,7 @@
*
* @hide
*/
+ // LINT.IfChange(dynamic_property_update)
public void updateDynamicallyConfigurableProperties(IPlatformCompat platformCompat,
AccessibilityServiceInfo other) {
if (isRequestAccessibilityButtonChangeEnabled(platformCompat)) {
@@ -828,6 +890,7 @@
// NOTE: Ensure that only properties that are safe to be modified by the service itself
// are included here (regardless of hidden setters, etc.).
}
+ // LINT.ThenChange(:dynamic_property_defaults)
private boolean isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat) {
if (mResolveInfo == null) {
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index f902439..015c35e 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -10,6 +10,13 @@
}
flag {
+ name: "resettable_dynamic_properties"
+ namespace: "accessibility"
+ description: "Maintains initial copies of a11yServiceInfo dynamic properties so they can reset on disconnect."
+ bug: "312386990"
+}
+
+flag {
name: "cleanup_a11y_overlays"
namespace: "accessibility"
description: "Removes all attached accessibility overlays when a service is removed."
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 1d73843..b64c74e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -1685,6 +1685,9 @@
}
public void resetLocked() {
+ if (Flags.resettableDynamicProperties()) {
+ mAccessibilityServiceInfo.resetDynamicallyConfigurableProperties();
+ }
mSystemSupport.getKeyEventDispatcher().flush(this);
try {
// Clear the proxy in the other process so this
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index c58cb72..87b57b0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -23,9 +23,9 @@
import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_FINGERPRINT;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_INPUT_FILTER;
+import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_PACKAGE_BROADCAST_RECEIVER;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_USER_BROADCAST_RECEIVER;
-import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 2f0257a..ef80b59 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -16,6 +16,8 @@
package com.android.server.accessibility;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -24,6 +26,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -88,7 +91,7 @@
@Mock AccessibilityUserState mMockUserState;
@Mock Context mMockContext;
- @Mock AccessibilityServiceInfo mMockServiceInfo;
+ AccessibilityServiceInfo mServiceInfo;
@Mock ResolveInfo mMockResolveInfo;
@Mock AccessibilitySecurityPolicy mMockSecurityPolicy;
@Mock AccessibilityWindowManager mMockA11yWindowManager;
@@ -115,7 +118,8 @@
when(mMockSystemSupport.getMotionEventInjectorForDisplayLocked(
Display.DEFAULT_DISPLAY)).thenReturn(mMockMotionEventInjector);
- when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
+ mServiceInfo = spy(new AccessibilityServiceInfo());
+ when(mServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
mMockResolveInfo.serviceInfo = mock(ServiceInfo.class);
mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
@@ -125,7 +129,7 @@
.thenReturn(new DisplayManager(mMockContext));
mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
- COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(),
+ COMPONENT_NAME, mServiceInfo, SERVICE_ID, mHandler, new Object(),
mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace,
mMockWindowManagerInternal, mMockSystemActionPerformer,
mMockA11yWindowManager, mMockActivityTaskManagerInternal);
@@ -286,4 +290,22 @@
verify(mMockMagnificationProcessor).resetAllIfNeeded(anyInt());
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_RESETTABLE_DYNAMIC_PROPERTIES)
+ public void binderDied_resetA11yServiceInfo() {
+ final int flag = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
+ setServiceBinding(COMPONENT_NAME);
+ mConnection.bindLocked();
+ mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder);
+ AccessibilityServiceInfo info = mConnection.getServiceInfo();
+ assertThat(info.flags & flag).isEqualTo(0);
+
+ info = mConnection.getServiceInfo();
+ info.flags |= flag;
+ mConnection.setServiceInfo(info);
+ assertThat(mConnection.getServiceInfo().flags & flag).isEqualTo(flag);
+
+ mConnection.binderDied();
+ assertThat(mConnection.getServiceInfo().flags & flag).isEqualTo(0);
+ }
}