Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 275ad1df authored by Riley Jones's avatar Riley Jones
Browse files

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
parent 6803757a
Loading
Loading
Loading
Loading
+65 −2
Original line number Diff line number Diff line
@@ -647,11 +647,44 @@ public class AccessibilityServiceInfo implements Parcelable {

    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);
    }

    /**
@@ -793,8 +826,36 @@ public class AccessibilityServiceInfo implements Parcelable {
            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.
@@ -808,6 +869,7 @@ public class AccessibilityServiceInfo implements Parcelable {
     *
     * @hide
     */
    // LINT.IfChange(dynamic_property_update)
    public void updateDynamicallyConfigurableProperties(IPlatformCompat platformCompat,
            AccessibilityServiceInfo other) {
        if (isRequestAccessibilityButtonChangeEnabled(platformCompat)) {
@@ -828,6 +890,7 @@ public class AccessibilityServiceInfo implements Parcelable {
        // 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) {
+7 −0
Original line number Diff line number Diff line
@@ -9,6 +9,13 @@ flag {
    bug: "297972548"
}

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"
+3 −0
Original line number Diff line number Diff line
@@ -1685,6 +1685,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
    }

    public void resetLocked() {
        if (Flags.resettableDynamicProperties()) {
            mAccessibilityServiceInfo.resetDynamicallyConfigurableProperties();
        }
        mSystemSupport.getKeyEventDispatcher().flush(this);
        try {
            // Clear the proxy in the other process so this
+1 −1
Original line number Diff line number Diff line
@@ -23,9 +23,9 @@ import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILIT
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;
+25 −3
Original line number Diff line number Diff line
@@ -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.anyInt;
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 @@ public class AccessibilityServiceConnectionTest {

    @Mock AccessibilityUserState mMockUserState;
    @Mock Context mMockContext;
    @Mock AccessibilityServiceInfo mMockServiceInfo;
    AccessibilityServiceInfo mServiceInfo;
    @Mock ResolveInfo mMockResolveInfo;
    @Mock AccessibilitySecurityPolicy mMockSecurityPolicy;
    @Mock AccessibilityWindowManager mMockA11yWindowManager;
@@ -115,7 +118,8 @@ public class AccessibilityServiceConnectionTest {
        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 @@ public class AccessibilityServiceConnectionTest {
                .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 @@ public class AccessibilityServiceConnectionTest {
        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);
    }
}