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

Commit 03a65b04 authored by Phil Weaver's avatar Phil Weaver
Browse files

Enhance a11y soft keyboard controller

Allow a11y services to request that the soft keyboard be
shown even when the hard keyboard is attached.

Defer to users who override this behavior, and put things
back the way they were when a service requesting this
behavior stops.

Bug: 31012180
Test: Adding CTS tests in linked CL, ran a11y unit tests,
modified TestBack to use the new flag and verified behavior
with a hard keyboard and verfied that settings behave as
expected when overriding and rebooting.
Change-Id: I530481e102ac376a4506b662862ee1ee74815b40
parent e9053378
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -2818,6 +2818,7 @@ package android.accessibilityservice {
    field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
    field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
    field public static final int SHOW_MODE_AUTO = 0; // 0x0
    field public static final int SHOW_MODE_AUTO = 0; // 0x0
    field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
    field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
    field public static final int SHOW_MODE_WITH_HARD_KEYBOARD = 2; // 0x2
  }
  }
  public static abstract class AccessibilityService.GestureResultCallback {
  public static abstract class AccessibilityService.GestureResultCallback {
+82 −22
Original line number Original line Diff line number Diff line
@@ -31,7 +31,6 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.RemoteException;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Log;
import android.util.Slog;
import android.util.Slog;
@@ -398,13 +397,49 @@ public abstract class AccessibilityService extends Service {
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "SHOW_MODE_" }, value = {
    @IntDef(prefix = { "SHOW_MODE_" }, value = {
            SHOW_MODE_AUTO,
            SHOW_MODE_AUTO,
            SHOW_MODE_HIDDEN
            SHOW_MODE_HIDDEN,
            SHOW_MODE_WITH_HARD_KEYBOARD
    })
    })
    public @interface SoftKeyboardShowMode {}
    public @interface SoftKeyboardShowMode {}


    /**
     * Allow the system to control when the soft keyboard is shown.
     * @see SoftKeyboardController
     */
    public static final int SHOW_MODE_AUTO = 0;
    public static final int SHOW_MODE_AUTO = 0;

    /**
     * Never show the soft keyboard.
     * @see SoftKeyboardController
     */
    public static final int SHOW_MODE_HIDDEN = 1;
    public static final int SHOW_MODE_HIDDEN = 1;


    /**
     * Allow the soft keyboard to be shown, even if a hard keyboard is connected
     * @see SoftKeyboardController
     */
    public static final int SHOW_MODE_WITH_HARD_KEYBOARD = 2;

    /**
     * Mask used to cover the show modes supported in public API
     * @hide
     */
    public static final int SHOW_MODE_MASK = 0x03;

    /**
     * Bit used to hold the old value of the hard IME setting to restore when a service is shut
     * down.
     * @hide
     */
    public static final int SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE = 0x20000000;

    /**
     * Bit for show mode setting to indicate that the user has overridden the hard keyboard
     * behavior.
     * @hide
     */
    public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000;

    private int mConnectionId = AccessibilityInteractionClient.NO_ID;
    private int mConnectionId = AccessibilityInteractionClient.NO_ID;


    private AccessibilityServiceInfo mInfo;
    private AccessibilityServiceInfo mInfo;
@@ -1147,7 +1182,27 @@ public abstract class AccessibilityService extends Service {
    }
    }


    /**
    /**
     * Used to control and query the soft keyboard show mode.
     * Used to control, query, and listen for changes to the soft keyboard show mode.
     * <p>
     * Accessibility services may request to override the decisions normally made about whether or
     * not the soft keyboard is shown.
     * <p>
     * If multiple services make conflicting requests, the last request is honored. A service may
     * register a listener to find out if the mode has changed under it.
     * <p>
     * If the user takes action to override the behavior behavior requested by an accessibility
     * service, the user's request takes precendence, the show mode will be reset to
     * {@link AccessibilityService#SHOW_MODE_AUTO}, and services will no longer be able to control
     * that aspect of the soft keyboard's behavior.
     * <p>
     * Note: Because soft keyboards are independent apps, the framework does not have total control
     * over their behavior. They may choose to show themselves, or not, without regard to requests
     * made here. So the framework will make a best effort to deliver the behavior requested, but
     * cannot guarantee success.
     *
     * @see AccessibilityService#SHOW_MODE_AUTO
     * @see AccessibilityService#SHOW_MODE_HIDDEN
     * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
     */
     */
    public static final class SoftKeyboardController {
    public static final class SoftKeyboardController {
        private final AccessibilityService mService;
        private final AccessibilityService mService;
@@ -1217,7 +1272,8 @@ public abstract class AccessibilityService extends Service {
         * @param listener the listener to remove, must be non-null
         * @param listener the listener to remove, must be non-null
         * @return {@code true} if the listener was removed, {@code false} otherwise
         * @return {@code true} if the listener was removed, {@code false} otherwise
         */
         */
        public boolean removeOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
        public boolean removeOnShowModeChangedListener(
                @NonNull OnShowModeChangedListener listener) {
            if (mListeners == null) {
            if (mListeners == null) {
                return false;
                return false;
            }
            }
@@ -1289,32 +1345,32 @@ public abstract class AccessibilityService extends Service {
        }
        }


        /**
        /**
         * Returns the show mode of the soft keyboard. The default show mode is
         * Returns the show mode of the soft keyboard.
         * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
         * focused. An AccessibilityService can also request the show mode
         * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
         *
         *
         * @return the current soft keyboard show mode
         * @return the current soft keyboard show mode
         *
         * @see AccessibilityService#SHOW_MODE_AUTO
         * @see AccessibilityService#SHOW_MODE_HIDDEN
         * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
         */
         */
        @SoftKeyboardShowMode
        @SoftKeyboardShowMode
        public int getShowMode() {
        public int getShowMode() {
            final IAccessibilityServiceConnection connection =
                    AccessibilityInteractionClient.getInstance().getConnection(
                            mService.mConnectionId);
            if (connection != null) {
                try {
                try {
               return Settings.Secure.getInt(mService.getContentResolver(),
                    return connection.getSoftKeyboardShowMode();
                       Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
                } catch (RemoteException re) {
           } catch (Settings.SettingNotFoundException e) {
                    Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
               Log.v(LOG_TAG, "Failed to obtain the soft keyboard mode", e);
                    re.rethrowFromSystemServer();
               // The settings hasn't been changed yet, so it's value is null. Return the default.
                }
               return 0;
            }
            }
            return SHOW_MODE_AUTO;
        }
        }


        /**
        /**
         * Sets the soft keyboard show mode. The default show mode is
         * Sets the soft keyboard show mode.
         * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
         * focused. An AccessibilityService can also request the show mode
         * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
         * The lastto this method will be honored, regardless of any previous calls (including those
         * made by other AccessibilityServices).
         * <p>
         * <p>
         * <strong>Note:</strong> If the service is not yet connected (e.g.
         * <strong>Note:</strong> If the service is not yet connected (e.g.
         * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
         * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
@@ -1322,6 +1378,10 @@ public abstract class AccessibilityService extends Service {
         *
         *
         * @param showMode the new show mode for the soft keyboard
         * @param showMode the new show mode for the soft keyboard
         * @return {@code true} on success
         * @return {@code true} on success
         *
         * @see AccessibilityService#SHOW_MODE_AUTO
         * @see AccessibilityService#SHOW_MODE_HIDDEN
         * @see AccessibilityService#SHOW_MODE_WITH_HARD_KEYBOARD
         */
         */
        public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
        public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
           final IAccessibilityServiceConnection connection =
           final IAccessibilityServiceConnection connection =
+2 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,8 @@ interface IAccessibilityServiceConnection {


    boolean setSoftKeyboardShowMode(int showMode);
    boolean setSoftKeyboardShowMode(int showMode);


    int getSoftKeyboardShowMode();

    void setSoftKeyboardCallbackEnabled(boolean enabled);
    void setSoftKeyboardCallbackEnabled(boolean enabled);


    boolean isAccessibilityButtonAvailable();
    boolean isAccessibilityButtonAvailable();
+4 −0
Original line number Original line Diff line number Diff line
@@ -119,6 +119,10 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
        return false;
        return false;
    }
    }


    public int getSoftKeyboardShowMode() {
        return 0;
    }

    public void setSoftKeyboardCallbackEnabled(boolean enabled) {}
    public void setSoftKeyboardCallbackEnabled(boolean enabled) {}


    public boolean isAccessibilityButtonAvailable() {
    public boolean isAccessibilityButtonAvailable() {
+157 −48
Original line number Original line Diff line number Diff line
@@ -16,12 +16,18 @@


package com.android.server.accessibility;
package com.android.server.accessibility;


import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_WITH_HARD_KEYBOARD;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;


import android.Manifest;
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityService;
@@ -1779,7 +1785,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        updateDisplayDaltonizerLocked(userState);
        updateDisplayDaltonizerLocked(userState);
        updateDisplayInversionLocked(userState);
        updateDisplayInversionLocked(userState);
        updateMagnificationLocked(userState);
        updateMagnificationLocked(userState);
        updateSoftKeyboardShowModeLocked(userState);
        scheduleUpdateFingerprintGestureHandling(userState);
        scheduleUpdateFingerprintGestureHandling(userState);
        scheduleUpdateInputFilter(userState);
        scheduleUpdateInputFilter(userState);
        scheduleUpdateClientsIfNeededLocked(userState);
        scheduleUpdateClientsIfNeededLocked(userState);
@@ -1973,18 +1978,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        return false;
        return false;
    }
    }


    private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) {
        final int softKeyboardShowMode = Settings.Secure.getIntForUser(
                mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0,
                userState.mUserId);
        if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) {
            userState.mSoftKeyboardShowMode = softKeyboardShowMode;
            return true;
        }
        return false;
    }

    private void updateTouchExplorationLocked(UserState userState) {
    private void updateTouchExplorationLocked(UserState userState) {
        boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
        boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
        final int serviceCount = userState.mBoundServices.size();
        final int serviceCount = userState.mBoundServices.size();
@@ -2183,34 +2176,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        return false;
        return false;
    }
    }


    private void updateSoftKeyboardShowModeLocked(UserState userState) {
        final int userId = userState.mUserId;
        // Only check whether we need to reset the soft keyboard mode if it is not set to the
        // default.
        if ((userId == mCurrentUserId) && (userState.mSoftKeyboardShowMode != 0)) {
            // Check whether the last AccessibilityService that changed the soft keyboard mode to
            // something other than the default is still enabled and, if not, remove flag and
            // reset to the default soft keyboard behavior.
            boolean serviceChangingSoftKeyboardModeIsEnabled =
                    userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode);

            if (!serviceChangingSoftKeyboardModeIsEnabled) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    Settings.Secure.putIntForUser(mContext.getContentResolver(),
                            Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                            0,
                            userState.mUserId);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
                userState.mSoftKeyboardShowMode = 0;
                userState.mServiceChangingSoftKeyboardMode = null;
                notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
            }
        }
    }

    private void updateFingerprintGestureHandling(UserState userState) {
    private void updateFingerprintGestureHandling(UserState userState) {
        final List<AccessibilityServiceConnection> services;
        final List<AccessibilityServiceConnection> services;
        synchronized (mLock) {
        synchronized (mLock) {
@@ -2445,6 +2410,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        }
        }
    }
    }


    private void putSecureIntForUser(String key, int value, int userid) {
        final long identity = Binder.clearCallingIdentity();
        try {
            Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userid);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    class RemoteAccessibilityConnection implements DeathRecipient {
    class RemoteAccessibilityConnection implements DeathRecipient {
        private final int mUid;
        private final int mUid;
        private final String mPackageName;
        private final String mPackageName;
@@ -3667,7 +3641,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub


        public int mLastSentClientState = -1;
        public int mLastSentClientState = -1;


        public int mSoftKeyboardShowMode = 0;
        private int mSoftKeyboardShowMode = 0;


        public boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
        public boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
        public ComponentName mServiceAssignedToAccessibilityButton;
        public ComponentName mServiceAssignedToAccessibilityButton;
@@ -3728,7 +3702,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            mServiceAssignedToAccessibilityButton = null;
            mServiceAssignedToAccessibilityButton = null;
            mIsNavBarMagnificationAssignedToAccessibilityButton = false;
            mIsNavBarMagnificationAssignedToAccessibilityButton = false;
            mIsAutoclickEnabled = false;
            mIsAutoclickEnabled = false;
            mSoftKeyboardShowMode = 0;
        }
        }


        public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
        public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
@@ -3750,6 +3723,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        public void removeServiceLocked(AccessibilityServiceConnection serviceConnection) {
        public void removeServiceLocked(AccessibilityServiceConnection serviceConnection) {
            mBoundServices.remove(serviceConnection);
            mBoundServices.remove(serviceConnection);
            serviceConnection.onRemoved();
            serviceConnection.onRemoved();
            if ((mServiceChangingSoftKeyboardMode != null)
                    && (mServiceChangingSoftKeyboardMode.equals(
                            serviceConnection.getServiceInfo().getComponentName()))) {
                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
            }
            // It may be possible to bind a service twice, which confuses the map. Rebuild the map
            // It may be possible to bind a service twice, which confuses the map. Rebuild the map
            // to make sure we can still reach a service
            // to make sure we can still reach a service
            mComponentNameToServiceMap.clear();
            mComponentNameToServiceMap.clear();
@@ -3776,6 +3754,134 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        public Set<ComponentName> getBindingServicesLocked() {
        public Set<ComponentName> getBindingServicesLocked() {
            return mBindingServices;
            return mBindingServices;
        }
        }

        public int getSoftKeyboardShowMode() {
            return mSoftKeyboardShowMode;
        }

        /**
         * Set the soft keyboard mode. This mode is a bit odd, as it spans multiple settings.
         * The ACCESSIBILITY_SOFT_KEYBOARD_MODE setting can be checked by the rest of the system
         * to see if it should suppress showing the IME. The SHOW_IME_WITH_HARD_KEYBOARD setting
         * setting can be changed by the user, and prevents the system from suppressing the soft
         * keyboard when the hard keyboard is connected. The hard keyboard setting needs to defer
         * to the user's preference, if they have supplied one.
         *
         * @param newMode The new mode
         * @param requester The service requesting the change, so we can undo it when the
         *                  service stops. Set to null if something other than a service is forcing
         *                  the change.
         *
         * @return Whether or not the soft keyboard mode equals the new mode after the call
         */
        public boolean setSoftKeyboardModeLocked(int newMode, @Nullable ComponentName requester) {
            if ((newMode != SHOW_MODE_AUTO) && (newMode != SHOW_MODE_HIDDEN)
                    && (newMode != SHOW_MODE_WITH_HARD_KEYBOARD))
            {
                Slog.w(LOG_TAG, "Invalid soft keyboard mode");
                return false;
            }
            if (mSoftKeyboardShowMode == newMode) return true;

            if (newMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
                if (hasUserOverriddenHardKeyboardSettingLocked()) {
                    // The user has specified a default for this setting
                    return false;
                }
                // Save the original value. But don't do this if the value in settings is already
                // the new mode. That happens when we start up after a reboot, and we don't want
                // to overwrite the value we had from when we first started controlling the setting.
                if (getSoftKeyboardValueFromSettings() != SHOW_MODE_WITH_HARD_KEYBOARD) {
                    setOriginalHardKeyboardValue(
                            Settings.Secure.getInt(mContext.getContentResolver(),
                                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0);
                }
                putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId);
            } else if (mSoftKeyboardShowMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
                putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
                        getOriginalHardKeyboardValue() ? 1 : 0, mUserId);
            }

            saveSoftKeyboardValueToSettings(newMode);
            mSoftKeyboardShowMode = newMode;
            mServiceChangingSoftKeyboardMode = requester;
            notifySoftKeyboardShowModeChangedLocked(mSoftKeyboardShowMode);
            return true;
        }

        /**
         * If the settings are inconsistent with the internal state, make the internal state
         * match the settings.
         */
        public void reconcileSoftKeyboardModeWithSettingsLocked() {
            final ContentResolver cr = mContext.getContentResolver();
            final boolean showWithHardKeyboardSettings =
                    Settings.Secure.getInt(cr, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0;
            if (mSoftKeyboardShowMode == SHOW_MODE_WITH_HARD_KEYBOARD) {
                if (!showWithHardKeyboardSettings) {
                    // The user has overridden the setting. Respect that and prevent further changes
                    // to this behavior.
                    setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
                    setUserOverridesHardKeyboardSettingLocked();
                }
            }

            // If the setting and the internal state are out of sync, set both to default
            if (getSoftKeyboardValueFromSettings() != mSoftKeyboardShowMode)
            {
                Slog.e(LOG_TAG,
                        "Show IME setting inconsistent with internal state. Overwriting");
                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
                putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                        SHOW_MODE_AUTO, mUserId);
            }
        }

        private void setUserOverridesHardKeyboardSettingLocked() {
            final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                    softKeyboardSetting | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
                    mUserId);
        }

        private boolean hasUserOverriddenHardKeyboardSettingLocked() {
            final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
            return (softKeyboardSetting & SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN)
                    != 0;
        }

        private void setOriginalHardKeyboardValue(boolean originalHardKeyboardValue) {
            final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
            final int newSoftKeyboardSetting = oldSoftKeyboardSetting
                    & (~SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE)
                    | ((originalHardKeyboardValue) ? SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE : 0);
            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                    newSoftKeyboardSetting, mUserId);
        }

        private void saveSoftKeyboardValueToSettings(int softKeyboardShowMode) {
            final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
            final int newSoftKeyboardSetting = oldSoftKeyboardSetting & (~SHOW_MODE_MASK)
                    | softKeyboardShowMode;
            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                    newSoftKeyboardSetting, mUserId);
        }

        private int getSoftKeyboardValueFromSettings() {
            return Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                    SHOW_MODE_AUTO) & SHOW_MODE_MASK;
        }

        private boolean getOriginalHardKeyboardValue() {
            return (Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0)
                    & SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) != 0;
        }
    }
    }


    private final class AccessibilityContentObserver extends ContentObserver {
    private final class AccessibilityContentObserver extends ContentObserver {
@@ -3813,6 +3919,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
        private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);


        private final Uri mShowImeWithHardKeyboardUri = Settings.Secure.getUriFor(
                Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);

        private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor(
        private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor(
                Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
                Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);


@@ -3847,6 +3956,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                    mHighTextContrastUri, false, this, UserHandle.USER_ALL);
                    mHighTextContrastUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
            contentResolver.registerContentObserver(
                    mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
                    mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
                    mShowImeWithHardKeyboardUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
            contentResolver.registerContentObserver(
                    mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
                    mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
            contentResolver.registerContentObserver(
            contentResolver.registerContentObserver(
@@ -3890,11 +4001,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                    if (readHighTextContrastEnabledSettingLocked(userState)) {
                    if (readHighTextContrastEnabledSettingLocked(userState)) {
                        onUserStateChangedLocked(userState);
                        onUserStateChangedLocked(userState);
                    }
                    }
                } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
                } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)
                    if (readSoftKeyboardShowModeChangedLocked(userState)) {
                        || mShowImeWithHardKeyboardUri.equals(uri)) {
                        notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
                    userState.reconcileSoftKeyboardModeWithSettingsLocked();
                        onUserStateChangedLocked(userState);
                    }
                } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
                } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
                    if (readAccessibilityShortcutSettingLocked(userState)) {
                    if (readAccessibilityShortcutSettingLocked(userState)) {
                        onUserStateChangedLocked(userState);
                        onUserStateChangedLocked(userState);
Loading