Add DISMISS_NOTIFICATION_SHADE action for a11y
As discussed in b/159334261, although the current a11y use-cases for
closing the notification shade are already handled, it makes sense to
add an explicit global action for accessibility services to close the
notification shade (especially given there is one for opening the shade
already).
Added dependency to SystemActions, which required me to change add
SystemActions to SystemUIGoogleBinder (topic). I also added to
CarSystemUIBinder since SystemActions was also in their xml. I don't
know if I need to add to others (eg. Arc), please advise.
Bug: 159334261
Bug: 159105552
Test: With the shade opened, as a11y service send
GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE and verify shade is
closed.
Change-Id: If52a1763170d5a5efd6b4756794206fd8bfb18a0
This commit is contained in:
@@ -3015,6 +3015,7 @@ package android.accessibilityservice {
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER = 12; // 0xc
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_SHORTCUT = 13; // 0xd
|
||||
field public static final int GLOBAL_ACTION_BACK = 1; // 0x1
|
||||
field public static final int GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE = 15; // 0xf
|
||||
field public static final int GLOBAL_ACTION_HOME = 2; // 0x2
|
||||
field public static final int GLOBAL_ACTION_KEYCODE_HEADSETHOOK = 10; // 0xa
|
||||
field public static final int GLOBAL_ACTION_LOCK_SCREEN = 8; // 0x8
|
||||
|
||||
@@ -555,6 +555,11 @@ public abstract class AccessibilityService extends Service {
|
||||
*/
|
||||
public static final int GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS = 14;
|
||||
|
||||
/**
|
||||
* Action to dismiss the notification shade
|
||||
*/
|
||||
public static final int GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE = 15;
|
||||
|
||||
private static final String LOG_TAG = "AccessibilityService";
|
||||
|
||||
/**
|
||||
|
||||
@@ -5519,6 +5519,8 @@
|
||||
<string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label">On-screen Accessibility Shortcut Chooser</string>
|
||||
<!-- Label for triggering hardware accessibility shortcut action [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_system_action_hardware_a11y_shortcut_label">Accessibility Shortcut</string>
|
||||
<!-- Label for dismissing the notification shade [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_system_action_dismiss_notification_shade">Dismiss Notification Shade</string>
|
||||
<!-- Accessibility description of caption view -->
|
||||
<string name="accessibility_freeform_caption">Caption bar of <xliff:g id="app_name">%1$s</xliff:g>.</string>
|
||||
|
||||
|
||||
@@ -3964,6 +3964,7 @@
|
||||
<java-symbol type="string" name="accessibility_system_action_on_screen_a11y_shortcut_label" />
|
||||
<java-symbol type="string" name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" />
|
||||
<java-symbol type="string" name="accessibility_system_action_hardware_a11y_shortcut_label" />
|
||||
<java-symbol type="string" name="accessibility_system_action_dismiss_notification_shade" />
|
||||
|
||||
<java-symbol type="string" name="accessibility_freeform_caption" />
|
||||
|
||||
|
||||
@@ -53,12 +53,18 @@ import com.android.systemui.Dependency;
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.recents.Recents;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
|
||||
import com.android.systemui.util.Assert;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.Lazy;
|
||||
|
||||
/**
|
||||
* Class to register system actions with accessibility framework.
|
||||
*/
|
||||
@@ -128,23 +134,39 @@ public class SystemActions extends SystemUI {
|
||||
public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT =
|
||||
AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_SHORTCUT; // 13
|
||||
|
||||
public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE =
|
||||
AccessibilityService.GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE; // 15
|
||||
|
||||
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
|
||||
|
||||
private SystemActionsBroadcastReceiver mReceiver;
|
||||
private final SystemActionsBroadcastReceiver mReceiver;
|
||||
private Locale mLocale;
|
||||
private AccessibilityManager mA11yManager;
|
||||
private final AccessibilityManager mA11yManager;
|
||||
private final Lazy<StatusBar> mStatusBar;
|
||||
private final NotificationShadeWindowController mNotificationShadeController;
|
||||
private final StatusBarWindowCallback mNotificationShadeCallback;
|
||||
private boolean mDismissNotificationShadeActionRegistered;
|
||||
|
||||
@Inject
|
||||
public SystemActions(Context context) {
|
||||
public SystemActions(Context context,
|
||||
NotificationShadeWindowController notificationShadeController,
|
||||
Lazy<StatusBar> statusBar) {
|
||||
super(context);
|
||||
mReceiver = new SystemActionsBroadcastReceiver();
|
||||
mLocale = mContext.getResources().getConfiguration().getLocales().get(0);
|
||||
mA11yManager = (AccessibilityManager) mContext.getSystemService(
|
||||
Context.ACCESSIBILITY_SERVICE);
|
||||
mNotificationShadeController = notificationShadeController;
|
||||
// Saving in instance variable since to prevent GC since
|
||||
// NotificationShadeWindowController.registerCallback() only keeps weak references.
|
||||
mNotificationShadeCallback = (keyguardShowing, keyguardOccluded, bouncerShowing) ->
|
||||
registerOrUnregisterDismissNotificationShadeAction();
|
||||
mStatusBar = statusBar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
mNotificationShadeController.registerCallback(mNotificationShadeCallback);
|
||||
mContext.registerReceiverForAllUsers(
|
||||
mReceiver,
|
||||
mReceiver.createIntentFilter(),
|
||||
@@ -210,6 +232,32 @@ public class SystemActions extends SystemUI {
|
||||
mA11yManager.registerSystemAction(actionTakeScreenshot, SYSTEM_ACTION_ID_TAKE_SCREENSHOT);
|
||||
mA11yManager.registerSystemAction(
|
||||
actionAccessibilityShortcut, SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT);
|
||||
registerOrUnregisterDismissNotificationShadeAction();
|
||||
}
|
||||
|
||||
private void registerOrUnregisterDismissNotificationShadeAction() {
|
||||
Assert.isMainThread();
|
||||
|
||||
// Saving state in instance variable since this callback is called quite often to avoid
|
||||
// binder calls
|
||||
StatusBar statusBar = mStatusBar.get();
|
||||
if (statusBar.isPanelExpanded() && !statusBar.isKeyguardShowing()) {
|
||||
if (!mDismissNotificationShadeActionRegistered) {
|
||||
mA11yManager.registerSystemAction(
|
||||
createRemoteAction(
|
||||
R.string.accessibility_system_action_dismiss_notification_shade,
|
||||
SystemActionsBroadcastReceiver
|
||||
.INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE),
|
||||
SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE);
|
||||
mDismissNotificationShadeActionRegistered = true;
|
||||
}
|
||||
} else {
|
||||
if (mDismissNotificationShadeActionRegistered) {
|
||||
mA11yManager.unregisterSystemAction(
|
||||
SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE);
|
||||
mDismissNotificationShadeActionRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,10 +309,15 @@ public class SystemActions extends SystemUI {
|
||||
R.string.accessibility_system_action_on_screen_a11y_shortcut_chooser_label;
|
||||
intent = SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER;
|
||||
break;
|
||||
case SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT:
|
||||
case SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT:
|
||||
labelId = R.string.accessibility_system_action_hardware_a11y_shortcut_label;
|
||||
intent = SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_SHORTCUT;
|
||||
break;
|
||||
case SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE:
|
||||
labelId = R.string.accessibility_system_action_dismiss_notification_shade;
|
||||
intent = SystemActionsBroadcastReceiver
|
||||
.INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -369,6 +422,10 @@ public class SystemActions extends SystemUI {
|
||||
mA11yManager.performAccessibilityShortcut();
|
||||
}
|
||||
|
||||
private void handleAccessibilityDismissNotificationShade() {
|
||||
mStatusBar.get().animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, false /* force */);
|
||||
}
|
||||
|
||||
private class SystemActionsBroadcastReceiver extends BroadcastReceiver {
|
||||
private static final String INTENT_ACTION_BACK = "SYSTEM_ACTION_BACK";
|
||||
private static final String INTENT_ACTION_HOME = "SYSTEM_ACTION_HOME";
|
||||
@@ -384,6 +441,8 @@ public class SystemActions extends SystemUI {
|
||||
"SYSTEM_ACTION_ACCESSIBILITY_BUTTON_MENU";
|
||||
private static final String INTENT_ACTION_ACCESSIBILITY_SHORTCUT =
|
||||
"SYSTEM_ACTION_ACCESSIBILITY_SHORTCUT";
|
||||
private static final String INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE =
|
||||
"SYSTEM_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE";
|
||||
|
||||
private PendingIntent createPendingIntent(Context context, String intentAction) {
|
||||
switch (intentAction) {
|
||||
@@ -397,7 +456,8 @@ public class SystemActions extends SystemUI {
|
||||
case INTENT_ACTION_TAKE_SCREENSHOT:
|
||||
case INTENT_ACTION_ACCESSIBILITY_BUTTON:
|
||||
case INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER:
|
||||
case INTENT_ACTION_ACCESSIBILITY_SHORTCUT: {
|
||||
case INTENT_ACTION_ACCESSIBILITY_SHORTCUT:
|
||||
case INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE: {
|
||||
Intent intent = new Intent(intentAction);
|
||||
intent.setPackage(context.getPackageName());
|
||||
return PendingIntent.getBroadcast(context, 0, intent,
|
||||
@@ -422,6 +482,7 @@ public class SystemActions extends SystemUI {
|
||||
intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_BUTTON);
|
||||
intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER);
|
||||
intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_SHORTCUT);
|
||||
intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE);
|
||||
return intentFilter;
|
||||
}
|
||||
|
||||
@@ -473,6 +534,10 @@ public class SystemActions extends SystemUI {
|
||||
handleAccessibilityShortcut();
|
||||
break;
|
||||
}
|
||||
case INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE: {
|
||||
handleAccessibilityDismissNotificationShade();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -334,13 +334,6 @@ public class DependencyProvider {
|
||||
return WindowManagerWrapper.getInstance();
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@SysUISingleton
|
||||
public SystemActions providesSystemActions(Context context) {
|
||||
return new SystemActions(context);
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@SysUISingleton
|
||||
|
||||
Reference in New Issue
Block a user