summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/accessibility/AccessibilityShortcutController.java116
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
*/