diff options
| -rw-r--r-- | core/java/com/android/internal/accessibility/AccessibilityShortcutController.java | 116 |
1 files changed, 106 insertions, 10 deletions
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java index 40ca9fb22d09..43be0312245e 100644 --- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java +++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java @@ -16,6 +16,7 @@ package com.android.internal.accessibility; +import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; @@ -107,6 +108,8 @@ public class AccessibilityShortcutController { private final Context mContext; private final Handler mHandler; + private final UserSetupCompleteObserver mUserSetupCompleteObserver; + private AlertDialog mAlertDialog; private boolean mIsShortcutEnabled; private boolean mEnabledOnLockScreen; @@ -114,11 +117,11 @@ public class AccessibilityShortcutController { @Retention(RetentionPolicy.SOURCE) @IntDef({ - DialogStaus.NOT_SHOWN, - DialogStaus.SHOWN, + DialogStatus.NOT_SHOWN, + DialogStatus.SHOWN, }) /** Denotes the user shortcut type. */ - private @interface DialogStaus { + private @interface DialogStatus { int NOT_SHOWN = 0; int SHOWN = 1; } @@ -163,6 +166,7 @@ public class AccessibilityShortcutController { mContext = context; mHandler = handler; mUserId = initialUserId; + mUserSetupCompleteObserver = new UserSetupCompleteObserver(handler, initialUserId); // Keep track of state of shortcut settings final ContentObserver co = new ContentObserver(handler) { @@ -188,6 +192,7 @@ public class AccessibilityShortcutController { public void setCurrentUser(int currentUserId) { mUserId = currentUserId; onSettingsChanged(); + mUserSetupCompleteObserver.onUserSwitched(currentUserId); } /** @@ -206,7 +211,7 @@ public class AccessibilityShortcutController { final ContentResolver cr = mContext.getContentResolver(); // Enable the shortcut from the lockscreen by default if the dialog has been shown final int dialogAlreadyShown = Settings.Secure.getIntForUser( - cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStaus.NOT_SHOWN, + cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStatus.NOT_SHOWN, mUserId); mEnabledOnLockScreen = Settings.Secure.getIntForUser( cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, @@ -222,7 +227,7 @@ public class AccessibilityShortcutController { final ContentResolver cr = mContext.getContentResolver(); final int userId = ActivityManager.getCurrentUser(); final int dialogAlreadyShown = Settings.Secure.getIntForUser( - cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStaus.NOT_SHOWN, + cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStatus.NOT_SHOWN, userId); // Play a notification vibration Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); @@ -234,7 +239,7 @@ public class AccessibilityShortcutController { vibrator.vibrate(vibePattern, -1, VIBRATION_ATTRIBUTES); } - if (dialogAlreadyShown == 0) { + if (dialogAlreadyShown == DialogStatus.NOT_SHOWN) { // The first time, we show a warning rather than toggle the service to give the user a // chance to turn off this feature before stuff gets enabled. mAlertDialog = createShortcutWarningDialog(userId); @@ -250,7 +255,7 @@ public class AccessibilityShortcutController { w.setAttributes(attr); mAlertDialog.show(); Settings.Secure.putIntForUser( - cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStaus.SHOWN, + cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStatus.SHOWN, userId); } else { playNotificationTone(); @@ -320,13 +325,13 @@ public class AccessibilityShortcutController { // If canceled, treat as if the dialog has never been shown Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, - DialogStaus.NOT_SHOWN, userId); + DialogStatus.NOT_SHOWN, userId); }) .setOnCancelListener((DialogInterface d) -> { // If canceled, treat as if the dialog has never been shown Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, - DialogStaus.NOT_SHOWN, userId); + DialogStatus.NOT_SHOWN, userId); }) .create(); return alertDialog; @@ -398,7 +403,7 @@ public class AccessibilityShortcutController { AccessibilityManager accessibilityManager = mFrameworkObjectProvider.getAccessibilityManagerInstance(mContext); return accessibilityManager.getEnabledAccessibilityServiceList( - AccessibilityServiceInfo.FEEDBACK_ALL_MASK).contains(serviceInfo); + FEEDBACK_ALL_MASK).contains(serviceInfo); } private boolean hasFeatureLeanback() { @@ -559,6 +564,97 @@ public class AccessibilityShortcutController { } } + private class UserSetupCompleteObserver extends ContentObserver { + + private boolean mIsRegistered = false; + private int mUserId; + + /** + * Creates a content observer. + * + * @param handler The handler to run {@link #onChange} on, or null if none. + * @param userId The current user id. + */ + UserSetupCompleteObserver(Handler handler, int userId) { + super(handler); + mUserId = userId; + if (!isUserSetupComplete()) { + registerObserver(); + } + } + + private boolean isUserSetupComplete() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0, mUserId) == 1; + } + + private void registerObserver() { + if (mIsRegistered) { + return; + } + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), + false, this, mUserId); + mIsRegistered = true; + } + + @Override + public void onChange(boolean selfChange) { + if (isUserSetupComplete()) { + unregisterObserver(); + setEmptyShortcutTargetIfNeeded(); + } + } + + private void unregisterObserver() { + if (!mIsRegistered) { + return; + } + mContext.getContentResolver().unregisterContentObserver(this); + mIsRegistered = false; + } + + /** + * Sets empty shortcut target if shortcut targets is not assigned and there is no any + * enabled service matching the default target after the setup wizard completed. + * + */ + private void setEmptyShortcutTargetIfNeeded() { + final ContentResolver contentResolver = mContext.getContentResolver(); + + final String shortcutTargets = Settings.Secure.getStringForUser(contentResolver, + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, mUserId); + if (shortcutTargets != null) { + return; + } + + final String defaultShortcutTarget = mContext.getString( + R.string.config_defaultAccessibilityService); + final List<AccessibilityServiceInfo> enabledServices = + mFrameworkObjectProvider.getAccessibilityManagerInstance( + mContext).getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK); + for (int i = enabledServices.size() - 1; i >= 0; i--) { + if (TextUtils.equals(defaultShortcutTarget, enabledServices.get(i).getId())) { + return; + } + } + + Settings.Secure.putStringForUser(contentResolver, + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "", mUserId); + } + + void onUserSwitched(int userId) { + if (mUserId == userId) { + return; + } + unregisterObserver(); + mUserId = userId; + if (!isUserSetupComplete()) { + registerObserver(); + } + } + } + /** * Immutable class to hold info about framework features that can be controlled by shortcut */ |