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

Commit 2abc23fe authored by Riley Jones's avatar Riley Jones Committed by Android (Google) Code Review
Browse files

Merge "Refactoring performAccessibilityShortcut" into main

parents 890113a7 c5d54570
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.view.accessibility;
import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_ENABLE_ACCESSIBILITY_VOLUME;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;

import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;

import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
@@ -62,6 +64,7 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.IWindow;
import android.view.SurfaceControl;
import android.view.View;
@@ -69,6 +72,7 @@ import android.view.accessibility.AccessibilityEvent.EventType;

import com.android.internal.R;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IntPair;

@@ -1565,7 +1569,7 @@ public final class AccessibilityManager {
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
    public void performAccessibilityShortcut() {
        performAccessibilityShortcut(null);
        performAccessibilityShortcut(Display.DEFAULT_DISPLAY, HARDWARE, null);
    }

    /**
@@ -1577,7 +1581,8 @@ public final class AccessibilityManager {
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
    public void performAccessibilityShortcut(@Nullable String targetName) {
    public void performAccessibilityShortcut(
            int displayId, @UserShortcutType int shortcutType, @Nullable String targetName) {
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
@@ -1586,7 +1591,7 @@ public final class AccessibilityManager {
            }
        }
        try {
            service.performAccessibilityShortcut(targetName);
            service.performAccessibilityShortcut(displayId, shortcutType, targetName);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error performing accessibility shortcut. ", re);
        }
@@ -1602,7 +1607,7 @@ public final class AccessibilityManager {
     */
    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
    public void enableShortcutsForTargets(boolean enable,
            @ShortcutConstants.UserShortcutType int shortcutTypes, @NonNull Set<String> targets,
            @UserShortcutType int shortcutTypes, @NonNull Set<String> targets,
            @UserIdInt int userId) {
        final IAccessibilityManager service;
        synchronized (mLock) {
@@ -1817,7 +1822,7 @@ public final class AccessibilityManager {
    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
    @NonNull
    public List<String> getAccessibilityShortcutTargets(
            @ShortcutConstants.UserShortcutType int shortcutType) {
            @UserShortcutType int shortcutType) {
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ interface IAccessibilityManager {
    void notifyAccessibilityButtonVisibilityChanged(boolean available);

    @EnforcePermission("MANAGE_ACCESSIBILITY")
    void performAccessibilityShortcut(String targetName);
    void performAccessibilityShortcut(int displayId, int shortcutType, String targetName);

    @EnforcePermission("MANAGE_ACCESSIBILITY")
    List<String> getAccessibilityShortcutTargets(int shortcutType);
+20 −9
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.internal.annotations.VisibleForTesting;

import java.util.Set;
@@ -67,6 +68,10 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS
    public AccessibilityTarget(Context context, @UserShortcutType int shortcutType,
            @AccessibilityFragmentType int fragmentType, boolean isShortcutSwitched, String id,
            int uid, CharSequence label, Drawable icon, String key) {
        if (!isRecognizedShortcutType(shortcutType)) {
            throw new IllegalArgumentException(
                    "Unexpected shortcut type " + ShortcutUtils.convertToKey(shortcutType));
        }
        mContext = context;
        mShortcutType = shortcutType;
        mFragmentType = fragmentType;
@@ -97,20 +102,15 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS
        holder.mStatusView.setVisibility(View.GONE);
    }

    @SuppressLint("MissingPermission")
    @Override
    public void onSelected() {
        final AccessibilityManager am =
                getContext().getSystemService(AccessibilityManager.class);
        switch (getShortcutType()) {
            case SOFTWARE:
                am.notifyAccessibilityButtonClicked(getContext().getDisplayId(), getId());
        if (am == null) {
            return;
            case HARDWARE:
                am.performAccessibilityShortcut(getId());
                return;
            default:
                throw new IllegalStateException("Unexpected shortcut type");
        }
        am.performAccessibilityShortcut(getContext().getDisplayId(), mShortcutType, getId());
    }

    @SuppressLint("MissingPermission")
@@ -188,4 +188,15 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS
    public String getKey() {
        return mKey;
    }

    /**
     * Determines if the provided shortcut type is valid for use with AccessibilityTargets.
     * @param shortcutType shortcut type to check.
     * @return {@code true} if the shortcut type can be used, {@code false} otherwise.
     */
    @VisibleForTesting
    public static boolean isRecognizedShortcutType(@UserShortcutType int shortcutType) {
        int mask = SOFTWARE | HARDWARE;
        return (shortcutType != 0 && (shortcutType & mask) == shortcutType);
    }
}
+21 −9
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.Collections;
@@ -159,21 +160,32 @@ public final class AccessibilityTargetHelper {

        final List<AccessibilityTarget> targets = new ArrayList<>(installedServices.size());
        for (AccessibilityServiceInfo info : installedServices) {
            final int targetSdk =
                    info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion;
            final boolean hasRequestAccessibilityButtonFlag =
                    (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
            if ((targetSdk <= Build.VERSION_CODES.Q) && !hasRequestAccessibilityButtonFlag
                    && (shortcutType == SOFTWARE)) {
                continue;
            }

            if (isValidServiceTarget(info, shortcutType)) {
                targets.add(createAccessibilityServiceTarget(context, shortcutType, info));
            }
        }

        return targets;
    }

    /**
     * Check for maintaining compatibility on prior versions.
     * Determines if a given service should be accumulated in a list of installed services.
     * @param info service info to check.
     * @param shortcutType type of shortcut to accumulate a list for.
     * @return {@code true} if the service should be added (always true past version Q),
     * otherwise {@code false}.
     */
    @VisibleForTesting
    public static boolean isValidServiceTarget(
            AccessibilityServiceInfo info, @UserShortcutType int shortcutType) {
        final boolean hasRequestAccessibilityButtonFlag =
                (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
        return (info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
                > Build.VERSION_CODES.Q) || hasRequestAccessibilityButtonFlag
                || shortcutType != SOFTWARE;
    }

    private static List<AccessibilityTarget> getAccessibilityActivityTargets(Context context,
            @UserShortcutType int shortcutType) {
        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+31 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.internal.accessibility.AccessibilityShortcutController
import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_TILE_COMPONENT_NAME;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;

import static com.google.common.truth.Truth.assertThat;

@@ -31,6 +32,8 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doThrow;
@@ -48,12 +51,14 @@ import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.view.Display;

import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.R;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.util.IntPair;
import com.android.server.accessibility.test.MessageCapturingHandler;
@@ -321,7 +326,7 @@ public class AccessibilityManagerTest {
        Throwable rethrownException = assertThrows(RuntimeException.class,
                () -> manager.enableShortcutsForTargets(
                        /* enable= */ false,
                        UserShortcutType.HARDWARE,
                        HARDWARE,
                        Set.of(DALTONIZER_COMPONENT_NAME.flattenToString()),
                        UserHandle.USER_CURRENT
                ));
@@ -331,7 +336,7 @@ public class AccessibilityManagerTest {
    @Test
    public void enableShortcutsForTargets_verifyServiceMethodCalled() throws Exception {
        AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
        int shortcutTypes = UserShortcutType.HARDWARE | UserShortcutType.TRIPLETAP;
        int shortcutTypes = HARDWARE | UserShortcutType.TRIPLETAP;

        manager.enableShortcutsForTargets(
                /* enable= */ false,
@@ -348,6 +353,30 @@ public class AccessibilityManagerTest {
        );
    }

    @Test
    public void performAccessibilityShortcut_callToService_defaultTypeIsHardware()
            throws Exception {
        AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);

        manager.performAccessibilityShortcut();

        verify(mMockService).performAccessibilityShortcut(
                eq(Display.DEFAULT_DISPLAY), eq(HARDWARE), isNull());
    }

    @Test
    public void performAccessibilityShortcut_callToService_typeParameterMatches() throws Exception {
        AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
        int display = Display.DEFAULT_DISPLAY;
        String name = LABEL;

        for (int type: ShortcutConstants.USER_SHORTCUT_TYPES) {
            manager.performAccessibilityShortcut(display, type, name);

            verify(mMockService).performAccessibilityShortcut(display, type, name);
        }
    }

    private class MyAccessibilityProxy extends AccessibilityDisplayProxy {
        MyAccessibilityProxy(int displayId,
                @NonNull List<AccessibilityServiceInfo> serviceInfos) {
Loading