Loading core/java/com/android/internal/accessibility/AccessibilityShortcutController.java +106 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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) { Loading @@ -188,6 +192,7 @@ public class AccessibilityShortcutController { public void setCurrentUser(int currentUserId) { mUserId = currentUserId; onSettingsChanged(); mUserSetupCompleteObserver.onUserSwitched(currentUserId); } /** Loading @@ -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, Loading @@ -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); Loading @@ -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); Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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 */ Loading Loading
core/java/com/android/internal/accessibility/AccessibilityShortcutController.java +106 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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) { Loading @@ -188,6 +192,7 @@ public class AccessibilityShortcutController { public void setCurrentUser(int currentUserId) { mUserId = currentUserId; onSettingsChanged(); mUserSetupCompleteObserver.onUserSwitched(currentUserId); } /** Loading @@ -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, Loading @@ -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); Loading @@ -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); Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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 */ Loading