Merge "Disable volume-key-accessibility shortcut upon exiting setup wizard" into tm-dev am: 6fcd7dd723

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17463205

Change-Id: Ibf77a5ffbb4e1b8f71e8888f5f1fbece139ea9f6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Ryan Lin
2022-04-08 02:11:45 +00:00
committed by Automerger Merge Worker

View File

@@ -16,6 +16,7 @@
package com.android.internal.accessibility; 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.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
@@ -107,6 +108,8 @@ public class AccessibilityShortcutController {
private final Context mContext; private final Context mContext;
private final Handler mHandler; private final Handler mHandler;
private final UserSetupCompleteObserver mUserSetupCompleteObserver;
private AlertDialog mAlertDialog; private AlertDialog mAlertDialog;
private boolean mIsShortcutEnabled; private boolean mIsShortcutEnabled;
private boolean mEnabledOnLockScreen; private boolean mEnabledOnLockScreen;
@@ -114,11 +117,11 @@ public class AccessibilityShortcutController {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
DialogStaus.NOT_SHOWN, DialogStatus.NOT_SHOWN,
DialogStaus.SHOWN, DialogStatus.SHOWN,
}) })
/** Denotes the user shortcut type. */ /** Denotes the user shortcut type. */
private @interface DialogStaus { private @interface DialogStatus {
int NOT_SHOWN = 0; int NOT_SHOWN = 0;
int SHOWN = 1; int SHOWN = 1;
} }
@@ -163,6 +166,7 @@ public class AccessibilityShortcutController {
mContext = context; mContext = context;
mHandler = handler; mHandler = handler;
mUserId = initialUserId; mUserId = initialUserId;
mUserSetupCompleteObserver = new UserSetupCompleteObserver(handler, initialUserId);
// Keep track of state of shortcut settings // Keep track of state of shortcut settings
final ContentObserver co = new ContentObserver(handler) { final ContentObserver co = new ContentObserver(handler) {
@@ -188,6 +192,7 @@ public class AccessibilityShortcutController {
public void setCurrentUser(int currentUserId) { public void setCurrentUser(int currentUserId) {
mUserId = currentUserId; mUserId = currentUserId;
onSettingsChanged(); onSettingsChanged();
mUserSetupCompleteObserver.onUserSwitched(currentUserId);
} }
/** /**
@@ -206,7 +211,7 @@ public class AccessibilityShortcutController {
final ContentResolver cr = mContext.getContentResolver(); final ContentResolver cr = mContext.getContentResolver();
// Enable the shortcut from the lockscreen by default if the dialog has been shown // Enable the shortcut from the lockscreen by default if the dialog has been shown
final int dialogAlreadyShown = Settings.Secure.getIntForUser( 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); mUserId);
mEnabledOnLockScreen = Settings.Secure.getIntForUser( mEnabledOnLockScreen = Settings.Secure.getIntForUser(
cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
@@ -222,7 +227,7 @@ public class AccessibilityShortcutController {
final ContentResolver cr = mContext.getContentResolver(); final ContentResolver cr = mContext.getContentResolver();
final int userId = ActivityManager.getCurrentUser(); final int userId = ActivityManager.getCurrentUser();
final int dialogAlreadyShown = Settings.Secure.getIntForUser( 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); userId);
// Play a notification vibration // Play a notification vibration
Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
@@ -234,7 +239,7 @@ public class AccessibilityShortcutController {
vibrator.vibrate(vibePattern, -1, VIBRATION_ATTRIBUTES); 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 // 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. // chance to turn off this feature before stuff gets enabled.
mAlertDialog = createShortcutWarningDialog(userId); mAlertDialog = createShortcutWarningDialog(userId);
@@ -250,7 +255,7 @@ public class AccessibilityShortcutController {
w.setAttributes(attr); w.setAttributes(attr);
mAlertDialog.show(); mAlertDialog.show();
Settings.Secure.putIntForUser( Settings.Secure.putIntForUser(
cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStaus.SHOWN, cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, DialogStatus.SHOWN,
userId); userId);
} else { } else {
playNotificationTone(); playNotificationTone();
@@ -320,13 +325,13 @@ public class AccessibilityShortcutController {
// If canceled, treat as if the dialog has never been shown // If canceled, treat as if the dialog has never been shown
Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
DialogStaus.NOT_SHOWN, userId); DialogStatus.NOT_SHOWN, userId);
}) })
.setOnCancelListener((DialogInterface d) -> { .setOnCancelListener((DialogInterface d) -> {
// If canceled, treat as if the dialog has never been shown // If canceled, treat as if the dialog has never been shown
Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
DialogStaus.NOT_SHOWN, userId); DialogStatus.NOT_SHOWN, userId);
}) })
.create(); .create();
return alertDialog; return alertDialog;
@@ -398,7 +403,7 @@ public class AccessibilityShortcutController {
AccessibilityManager accessibilityManager = AccessibilityManager accessibilityManager =
mFrameworkObjectProvider.getAccessibilityManagerInstance(mContext); mFrameworkObjectProvider.getAccessibilityManagerInstance(mContext);
return accessibilityManager.getEnabledAccessibilityServiceList( return accessibilityManager.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK).contains(serviceInfo); FEEDBACK_ALL_MASK).contains(serviceInfo);
} }
private boolean hasFeatureLeanback() { 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 * Immutable class to hold info about framework features that can be controlled by shortcut
*/ */