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

Commit ce687c5e authored by Phil Weaver's avatar Phil Weaver
Browse files

Restructure a11y shortcut settings

Separating the shortcut on/off from the shortcut service.
Enabling the shortcut to work from the lock screen if the
user wants it to.

Bug: 35872328
Bug: 35219988
Bug: 35443593
Test: Adjusted tests for shortcut controller, manually
activated shortcut in a variety of conditions.
Change-Id: Id39d33ec62eb5f11b76b2972089167dc7d4c625b
parent a359c984
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -5481,6 +5481,20 @@ public final class Settings {
         */
        public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";

        /**
         * Setting specifying if the accessibility shortcut is enabled.
         * @hide
         */
        public static final String ACCESSIBILITY_SHORTCUT_ENABLED =
                "accessibility_shortcut_enabled";

        /**
         * Setting specifying if the accessibility shortcut is enabled.
         * @hide
         */
        public static final String ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN =
                "accessibility_shortcut_on_lock_screen";

        /**
         * Setting specifying if the accessibility shortcut dialog has been shown to this user.
         * @hide
@@ -5489,7 +5503,7 @@ public final class Settings {
                "accessibility_shortcut_dialog_shown";

        /**
         * Setting specifying the the accessibility service to be toggled via the accessibility
         * Setting specifying the accessibility service to be toggled via the accessibility
         * shortcut. Must be its flattened {@link ComponentName}.
         * @hide
         */
@@ -6984,6 +6998,8 @@ public final class Settings {
            ACCESSIBILITY_ENABLED,
            ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
            ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
            ACCESSIBILITY_SHORTCUT_ENABLED,
            ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
            ACCESSIBILITY_SPEAK_PASSWORD,
            ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
            ACCESSIBILITY_CAPTIONING_PRESET,
+8 −6
Original line number Diff line number Diff line
@@ -3928,22 +3928,24 @@

    <!-- Dialog title for dialog shown when the accessibility shortcut is activated, and we want
     to confirm that the user understands what's going to happen-->
    <string name="accessibility_shortcut_warning_dialog_title">Accessibility Shortcut is ON</string>
    <string name="accessibility_shortcut_warning_dialog_title">Use Accessibility Shortcut?</string>

    <!-- Message shown in dialog when user is in the process of enabling the accessibility
    service via the volume buttons shortcut for the first time. [CHAR LIMIT=none] -->
    <string name="accessibility_shortcut_toogle_warning">
        Turn <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> on or off by holding down
        both volume buttons for 3 seconds.\n\nYou can change the service in
        Settings > Accessibility.
        When the shortcut is on, pressing both volume buttons for 3 seconds will start an
        accessibility feature.\n\n
        Current accessibility feature:\n
        <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g>\n\n
        You can change the feature in Settings > Accessibility.
    </string>

    <!-- Text in button that turns off the accessibility shortcut -->
    <string name="disable_accessibility_shortcut">Turn Off Shortcut</string>
    <string name="disable_accessibility_shortcut">Turn off Shortcut</string>

    <!-- Text in button that closes the warning dialog about the accessibility shortcut, leaving the
    shortcut enabled.-->
    <string name="leave_accessibility_shortcut_on">Leave on</string>
    <string name="leave_accessibility_shortcut_on">Use Shortcut</string>

    <!-- Text in toast to alert the user that the accessibility shortcut turned on an accessibility
    service.-->
+13 −0
Original line number Diff line number Diff line
@@ -169,6 +169,19 @@ public class AccessibilityUtils {
        return context.getString(R.string.config_defaultAccessibilityService);
    }

    /**
     * Check if the accessibility shortcut is enabled for a user
     *
     * @param context A valid context
     * @param userId The user of interest
     * @return {@code true} if the shortcut is enabled for the user. {@code false} otherwise.
     *         Note that the shortcut may be enabled, but no action associated with it.
     */
    public static boolean isShortcutEnabled(Context context, int userId) {
        return Settings.Secure.getIntForUser(context.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1, userId) == 1;
    }

    private static Set<ComponentName> getInstalledServices(Context context) {
        final Set<ComponentName> installedServices = new HashSet<>();
        installedServices.clear();
+5 −2
Original line number Diff line number Diff line
@@ -1920,7 +1920,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
        }
        ComponentName componentNameToEnable =
            ComponentName.unflattenFromString(componentNameToEnableString);
        if (componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) {
        if ((componentNameToEnable != null)
                && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) {
            return false;
        }
        userState.mServiceToEnableWithShortcut = componentNameToEnable;
@@ -1948,7 +1949,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
        if (!shortcutServiceIsInstalled) {
            userState.mServiceToEnableWithShortcut = null;
            Settings.Secure.putStringForUser(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "", userState.mUserId);
                    Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null, userState.mUserId);
            Settings.Secure.putIntForUser(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId);
        }
    }

+44 −19
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.database.ContentObserver;
import android.media.AudioAttributes;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.os.Vibrator;
@@ -58,6 +59,9 @@ public class AccessibilityShortcutController {
    private final Context mContext;
    private AlertDialog mAlertDialog;
    private boolean mIsShortcutEnabled;
    private boolean mEnabledOnLockScreen;
    private int mUserId;

    // Visible for testing
    public FrameworkObjectProvider mFrameworkObjectProvider = new FrameworkObjectProvider();

@@ -72,29 +76,55 @@ public class AccessibilityShortcutController {
        return context.getString(R.string.config_defaultAccessibilityService);
    }

    public AccessibilityShortcutController(Context context, Handler handler) {
    public AccessibilityShortcutController(Context context, Handler handler, int initialUserId) {
        mContext = context;

        // Keep track of state of shortcut
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE),
                false,
                new ContentObserver(handler) {
        // Keep track of state of shortcut settings
        final ContentObserver co = new ContentObserver(handler) {
            @Override
                    public void onChange(boolean selfChange) {
            public void onChange(boolean selfChange, Uri uri, int userId) {
                if (userId == mUserId) {
                    onSettingsChanged();
                }
                },
                UserHandle.USER_ALL);
        updateShortcutEnabled();
            }
        };
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE),
                false, co, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED),
                false, co, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN),
                false, co, UserHandle.USER_ALL);
        setCurrentUser(mUserId);
    }

    public void setCurrentUser(int currentUserId) {
        mUserId = currentUserId;
        onSettingsChanged();
    }

    public boolean isAccessibilityShortcutAvailable() {
        return mIsShortcutEnabled;
    /**
     * Check if the shortcut is available.
     *
     * @param onLockScreen Whether or not the phone is currently locked.
     *
     * @return {@code true} if the shortcut is available
     */
    public boolean isAccessibilityShortcutAvailable(boolean phoneLocked) {
        return mIsShortcutEnabled && (!phoneLocked || mEnabledOnLockScreen);
    }

    public void onSettingsChanged() {
        updateShortcutEnabled();
        final boolean haveValidService =
                !TextUtils.isEmpty(getTargetServiceComponentNameString(mContext, mUserId));
        final ContentResolver cr = mContext.getContentResolver();
        final boolean enabled = Settings.Secure.getIntForUser(
                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1, mUserId) == 1;
        mEnabledOnLockScreen = Settings.Secure.getIntForUser(
                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 0, mUserId) == 1;
        mIsShortcutEnabled = enabled && haveValidService;
    }

    /**
@@ -171,11 +201,6 @@ public class AccessibilityShortcutController {
        }
    }

    private void updateShortcutEnabled() {
        mIsShortcutEnabled = !TextUtils.isEmpty(getTargetServiceComponentNameString(
                mContext, UserHandle.myUserId()));
    }

    private AlertDialog createShortcutWarningDialog(int userId) {
        final AccessibilityServiceInfo serviceInfo = getInfoForTargetService();

Loading