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

Commit 4c547e76 authored by Sally Yuen's avatar Sally Yuen Committed by Android (Google) Code Review
Browse files

Merge "[EXO] Add aidl methods for registering and unregistering a proxy"

parents 260a7285 ab5975c6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -108,4 +108,10 @@ interface IAccessibilityManager {
    void setSystemAudioCaptioningUiEnabled(boolean isEnabled, int userId);

    oneway void setAccessibilityWindowAttributes(int displayId, int windowId, int userId, in AccessibilityWindowAttributes attributes);

    // Requires Manifest.permission.MANAGE_ACCESSIBILITY
    boolean registerProxyForDisplay(IAccessibilityServiceClient proxy, int displayId);

    // Requires Manifest.permission.MANAGE_ACCESSIBILITY
    boolean unregisterProxyForDisplay(int displayId);
}
+48 −1
Original line number Diff line number Diff line
@@ -277,6 +277,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
    final SparseArray<AccessibilityUserState> mUserStates = new SparseArray<>();

    private final UiAutomationManager mUiAutomationManager = new UiAutomationManager(mLock);
    private final ProxyManager mProxyManager;
    private final AccessibilityTraceManager mTraceManager;
    private final CaptioningManagerImpl mCaptioningManagerImpl;

@@ -396,7 +397,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            AccessibilityWindowManager a11yWindowManager,
            AccessibilityDisplayListener a11yDisplayListener,
            MagnificationController magnificationController,
            @Nullable AccessibilityInputFilter inputFilter) {
            @Nullable AccessibilityInputFilter inputFilter,
            ProxyManager proxyManager) {
        mContext = context;
        mPowerManager =  (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
@@ -412,6 +414,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        mMagnificationController = magnificationController;
        mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
        mCaptioningManagerImpl = new CaptioningManagerImpl(mContext);
        mProxyManager = proxyManager;
        if (inputFilter != null) {
            mInputFilter = inputFilter;
            mHasInputFilter = true;
@@ -445,6 +448,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                new MagnificationScaleProvider(mContext));
        mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
        mCaptioningManagerImpl = new CaptioningManagerImpl(mContext);
        mProxyManager = new ProxyManager(mLock);
        init();
    }

@@ -3601,6 +3605,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        mCaptioningManagerImpl.setSystemAudioCaptioningUiEnabled(isEnabled, userId);
    }

    @Override
    public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)
            throws RemoteException {
        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
        if (client == null) {
            return false;
        }
        if (displayId < 0) {
            throw new IllegalArgumentException("The display id " + displayId + " is invalid.");
        }
        if (displayId == Display.DEFAULT_DISPLAY) {
            throw new IllegalArgumentException("The default display cannot be proxy-ed.");
        }
        if (!isTrackedDisplay(displayId)) {
            throw new IllegalArgumentException("The display " + displayId + " does not exist or is"
                    + " not tracked by accessibility.");
        }

        mProxyManager.registerProxy(client, displayId);
        return true;
    }

    @Override
    public boolean unregisterProxyForDisplay(int displayId) throws RemoteException {
        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
        return mProxyManager.unregisterProxy(displayId);
    }

    @Override
    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
@@ -3830,6 +3862,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        return mA11yDisplayListener.getValidDisplayList();
    }


    /**
     *  Returns {@code true} if the display id is in the list of currently valid logical displays
     *  being tracked by a11y.
     */
    private boolean isTrackedDisplay(int displayId) {
        final ArrayList<Display> displays = getValidDisplayList();
        for (Display display : displays) {
            if (display.getDisplayId() == displayId) {
                return true;
            }
        }
        return false;
    }

    /**
     * A Utility class to handle display state.
     */
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.accessibility;
import android.accessibilityservice.IAccessibilityServiceClient;

/**
 * Manages proxy connections.
 *
 * Currently this acts similarly to UiAutomationManager as a global manager, though ideally each
 * proxy connection will belong to a separate user state.
 *
 * TODO(241117292): Remove or cut down during simultaneous user refactoring.
 */
public class ProxyManager {
    private final Object mLock;

    ProxyManager(Object lock) {
        mLock = lock;
    }

    /**
     * TODO: Create the proxy service connection.
     */
    public void registerProxy(IAccessibilityServiceClient client, int displayId) {
    }

    /**
     * TODO: Unregister the proxy service connection based on display id.
     */
    public boolean unregisterProxy(int displayId) {
        return true;
    }
}
+46 −1
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ public class AccessibilityManagerServiceTest {
    @Mock private WindowMagnificationManager mMockWindowMagnificationMgr;
    @Mock private MagnificationController mMockMagnificationController;
    @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
    @Mock private ProxyManager mProxyManager;

    @Rule
    public final TestableContext mTestableContext = new TestableContext(
@@ -184,7 +185,8 @@ public class AccessibilityManagerServiceTest {
                mMockA11yWindowManager,
                mMockA11yDisplayListener,
                mMockMagnificationController,
                mInputFilter);
                mInputFilter,
                mProxyManager);

        final AccessibilityUserState userState = new AccessibilityUserState(
                mA11yms.getCurrentUserIdLocked(), mTestableContext, mA11yms);
@@ -276,6 +278,49 @@ public class AccessibilityManagerServiceTest {
        verify(mMockServiceClient).onSystemActionsChanged();
    }

    @SmallTest
    @Test
    public void testRegisterProxy() throws Exception {
        mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
        verify(mProxyManager).registerProxy(mMockServiceClient, TEST_DISPLAY);
    }


    @SmallTest
    @Test
    public void testRegisterProxyWithoutPermission() throws Exception {
        doThrow(SecurityException.class).when(mMockSecurityPolicy)
                .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
        try {
            mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
            Assert.fail();
        } catch (SecurityException expected) {
        }
        verify(mProxyManager, never()).registerProxy(mMockServiceClient, TEST_DISPLAY);
    }

    @SmallTest
    @Test
    public void testRegisterProxyForDefaultDisplay() throws Exception {
        try {
            mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY);
            Assert.fail();
        } catch (IllegalArgumentException expected) {
        }
        verify(mProxyManager, never()).registerProxy(mMockServiceClient, Display.DEFAULT_DISPLAY);
    }

    @SmallTest
    @Test
    public void testRegisterProxyForInvalidDisplay() throws Exception {
        try {
            mA11yms.registerProxyForDisplay(mMockServiceClient, Display.INVALID_DISPLAY);
            Assert.fail();
        } catch (IllegalArgumentException expected) {
        }
        verify(mProxyManager, never()).registerProxy(mMockServiceClient, Display.INVALID_DISPLAY);
    }

    @SmallTest
    @Test
    public void testOnMagnificationTransitionFailed_capabilitiesIsAll_fallBackToPreviousMode() {