1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.accessibility;
18 
19 import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS;
20 
21 import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
22 
23 import android.accessibilityservice.AccessibilityService;
24 import android.app.PendingIntent;
25 import android.app.RemoteAction;
26 import android.content.BroadcastReceiver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.res.Configuration;
31 import android.graphics.drawable.Icon;
32 import android.hardware.input.InputManager;
33 import android.os.Handler;
34 import android.os.Looper;
35 import android.os.PowerManager;
36 import android.os.RemoteException;
37 import android.os.SystemClock;
38 import android.os.UserHandle;
39 import android.util.Log;
40 import android.view.Display;
41 import android.view.IWindowManager;
42 import android.view.InputDevice;
43 import android.view.KeyCharacterMap;
44 import android.view.KeyEvent;
45 import android.view.WindowManager;
46 import android.view.WindowManagerGlobal;
47 import android.view.accessibility.AccessibilityManager;
48 
49 import com.android.internal.R;
50 import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
51 import com.android.internal.util.ScreenshotHelper;
52 import com.android.systemui.SystemUI;
53 import com.android.systemui.dagger.SysUISingleton;
54 import com.android.systemui.recents.Recents;
55 import com.android.systemui.statusbar.CommandQueue;
56 import com.android.systemui.statusbar.NotificationShadeWindowController;
57 import com.android.systemui.statusbar.phone.StatusBar;
58 import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
59 import com.android.systemui.util.Assert;
60 
61 import java.util.Locale;
62 import java.util.Optional;
63 
64 import javax.inject.Inject;
65 
66 import dagger.Lazy;
67 
68 /**
69  * Class to register system actions with accessibility framework.
70  */
71 @SysUISingleton
72 public class SystemActions extends SystemUI {
73     private static final String TAG = "SystemActions";
74 
75     /**
76      * Action ID to go back.
77      */
78     private static final int SYSTEM_ACTION_ID_BACK = AccessibilityService.GLOBAL_ACTION_BACK; // = 1
79 
80     /**
81      * Action ID to go home.
82      */
83     private static final int SYSTEM_ACTION_ID_HOME = AccessibilityService.GLOBAL_ACTION_HOME; // = 2
84 
85     /**
86      * Action ID to toggle showing the overview of recent apps. Will fail on platforms that don't
87      * show recent apps.
88      */
89     private static final int SYSTEM_ACTION_ID_RECENTS =
90             AccessibilityService.GLOBAL_ACTION_RECENTS; // = 3
91 
92     /**
93      * Action ID to open the notifications.
94      */
95     private static final int SYSTEM_ACTION_ID_NOTIFICATIONS =
96             AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS; // = 4
97 
98     /**
99      * Action ID to open the quick settings.
100      */
101     private static final int SYSTEM_ACTION_ID_QUICK_SETTINGS =
102             AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS; // = 5
103 
104     /**
105      * Action ID to open the power long-press dialog.
106      */
107     private static final int SYSTEM_ACTION_ID_POWER_DIALOG =
108             AccessibilityService.GLOBAL_ACTION_POWER_DIALOG; // = 6
109 
110     /**
111      * Action ID to lock the screen
112      */
113     private static final int SYSTEM_ACTION_ID_LOCK_SCREEN =
114             AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN; // = 8
115 
116     /**
117      * Action ID to take a screenshot
118      */
119     private static final int SYSTEM_ACTION_ID_TAKE_SCREENSHOT =
120             AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT; // = 9
121 
122     /**
123      * Action ID to trigger the accessibility button
124      */
125     public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON =
126             AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_BUTTON; // 11
127 
128     /**
129      * Action ID to show accessibility button's menu of services
130      */
131     public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER =
132             AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER; // 12
133 
134     public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT =
135             AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_SHORTCUT; // 13
136 
137     public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE =
138             AccessibilityService.GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE; // 15
139 
140     private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
141 
142     private final SystemActionsBroadcastReceiver mReceiver;
143     private final Optional<Recents> mRecentsOptional;
144     private Locale mLocale;
145     private final AccessibilityManager mA11yManager;
146     private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
147     private final NotificationShadeWindowController mNotificationShadeController;
148     private final StatusBarWindowCallback mNotificationShadeCallback;
149     private boolean mDismissNotificationShadeActionRegistered;
150 
151     @Inject
SystemActions(Context context, NotificationShadeWindowController notificationShadeController, Lazy<Optional<StatusBar>> statusBarOptionalLazy, Optional<Recents> recentsOptional)152     public SystemActions(Context context,
153             NotificationShadeWindowController notificationShadeController,
154             Lazy<Optional<StatusBar>> statusBarOptionalLazy,
155             Optional<Recents> recentsOptional) {
156         super(context);
157         mRecentsOptional = recentsOptional;
158         mReceiver = new SystemActionsBroadcastReceiver();
159         mLocale = mContext.getResources().getConfiguration().getLocales().get(0);
160         mA11yManager = (AccessibilityManager) mContext.getSystemService(
161                 Context.ACCESSIBILITY_SERVICE);
162         mNotificationShadeController = notificationShadeController;
163         // Saving in instance variable since to prevent GC since
164         // NotificationShadeWindowController.registerCallback() only keeps weak references.
165         mNotificationShadeCallback = (keyguardShowing, keyguardOccluded, bouncerShowing, mDozing) ->
166                 registerOrUnregisterDismissNotificationShadeAction();
167         mStatusBarOptionalLazy = statusBarOptionalLazy;
168     }
169 
170     @Override
start()171     public void start() {
172         mNotificationShadeController.registerCallback(mNotificationShadeCallback);
173         mContext.registerReceiverForAllUsers(
174                 mReceiver,
175                 mReceiver.createIntentFilter(),
176                 PERMISSION_SELF,
177                 null);
178         registerActions();
179     }
180 
181     @Override
onConfigurationChanged(Configuration newConfig)182     public void onConfigurationChanged(Configuration newConfig) {
183         super.onConfigurationChanged(newConfig);
184         final Locale locale = mContext.getResources().getConfiguration().getLocales().get(0);
185         if (!locale.equals(mLocale)) {
186             mLocale = locale;
187             registerActions();
188         }
189     }
190 
registerActions()191     private void registerActions() {
192         RemoteAction actionBack = createRemoteAction(
193                 R.string.accessibility_system_action_back_label,
194                 SystemActionsBroadcastReceiver.INTENT_ACTION_BACK);
195 
196         RemoteAction actionHome = createRemoteAction(
197                 R.string.accessibility_system_action_home_label,
198                 SystemActionsBroadcastReceiver.INTENT_ACTION_HOME);
199 
200         RemoteAction actionRecents = createRemoteAction(
201                 R.string.accessibility_system_action_recents_label,
202                 SystemActionsBroadcastReceiver.INTENT_ACTION_RECENTS);
203 
204         RemoteAction actionNotifications = createRemoteAction(
205                 R.string.accessibility_system_action_notifications_label,
206                 SystemActionsBroadcastReceiver.INTENT_ACTION_NOTIFICATIONS);
207 
208         RemoteAction actionQuickSettings = createRemoteAction(
209                 R.string.accessibility_system_action_quick_settings_label,
210                 SystemActionsBroadcastReceiver.INTENT_ACTION_QUICK_SETTINGS);
211 
212         RemoteAction actionPowerDialog = createRemoteAction(
213                 R.string.accessibility_system_action_power_dialog_label,
214                 SystemActionsBroadcastReceiver.INTENT_ACTION_POWER_DIALOG);
215 
216         RemoteAction actionLockScreen = createRemoteAction(
217                 R.string.accessibility_system_action_lock_screen_label,
218                 SystemActionsBroadcastReceiver.INTENT_ACTION_LOCK_SCREEN);
219 
220         RemoteAction actionTakeScreenshot = createRemoteAction(
221                 R.string.accessibility_system_action_screenshot_label,
222                 SystemActionsBroadcastReceiver.INTENT_ACTION_TAKE_SCREENSHOT);
223 
224         RemoteAction actionAccessibilityShortcut = createRemoteAction(
225                 R.string.accessibility_system_action_hardware_a11y_shortcut_label,
226                 SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_SHORTCUT);
227 
228         mA11yManager.registerSystemAction(actionBack, SYSTEM_ACTION_ID_BACK);
229         mA11yManager.registerSystemAction(actionHome, SYSTEM_ACTION_ID_HOME);
230         mA11yManager.registerSystemAction(actionRecents, SYSTEM_ACTION_ID_RECENTS);
231         mA11yManager.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
232         mA11yManager.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
233         mA11yManager.registerSystemAction(actionPowerDialog, SYSTEM_ACTION_ID_POWER_DIALOG);
234         mA11yManager.registerSystemAction(actionLockScreen, SYSTEM_ACTION_ID_LOCK_SCREEN);
235         mA11yManager.registerSystemAction(actionTakeScreenshot, SYSTEM_ACTION_ID_TAKE_SCREENSHOT);
236         mA11yManager.registerSystemAction(
237                 actionAccessibilityShortcut, SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT);
238         registerOrUnregisterDismissNotificationShadeAction();
239     }
240 
registerOrUnregisterDismissNotificationShadeAction()241     private void registerOrUnregisterDismissNotificationShadeAction() {
242         Assert.isMainThread();
243 
244         // Saving state in instance variable since this callback is called quite often to avoid
245         // binder calls
246         final Optional<StatusBar> statusBarOptional = mStatusBarOptionalLazy.get();
247         if (statusBarOptional.map(StatusBar::isPanelExpanded).orElse(false)
248                 && !statusBarOptional.get().isKeyguardShowing()) {
249             if (!mDismissNotificationShadeActionRegistered) {
250                 mA11yManager.registerSystemAction(
251                         createRemoteAction(
252                                 R.string.accessibility_system_action_dismiss_notification_shade,
253                                 SystemActionsBroadcastReceiver
254                                         .INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE),
255                         SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE);
256                 mDismissNotificationShadeActionRegistered = true;
257             }
258         } else {
259             if (mDismissNotificationShadeActionRegistered) {
260                 mA11yManager.unregisterSystemAction(
261                         SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE);
262                 mDismissNotificationShadeActionRegistered = false;
263             }
264         }
265     }
266 
267     /**
268      * Register a system action.
269      * @param actionId the action ID to register.
270      */
register(int actionId)271     public void register(int actionId) {
272         int labelId;
273         String intent;
274         switch (actionId) {
275             case SYSTEM_ACTION_ID_BACK:
276                 labelId = R.string.accessibility_system_action_back_label;
277                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_BACK;
278                 break;
279             case SYSTEM_ACTION_ID_HOME:
280                 labelId = R.string.accessibility_system_action_home_label;
281                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_HOME;
282                 break;
283             case SYSTEM_ACTION_ID_RECENTS:
284                 labelId = R.string.accessibility_system_action_recents_label;
285                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_RECENTS;
286                 break;
287             case SYSTEM_ACTION_ID_NOTIFICATIONS:
288                 labelId = R.string.accessibility_system_action_notifications_label;
289                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_NOTIFICATIONS;
290                 break;
291             case SYSTEM_ACTION_ID_QUICK_SETTINGS:
292                 labelId = R.string.accessibility_system_action_quick_settings_label;
293                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_QUICK_SETTINGS;
294                 break;
295             case SYSTEM_ACTION_ID_POWER_DIALOG:
296                 labelId = R.string.accessibility_system_action_power_dialog_label;
297                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_POWER_DIALOG;
298                 break;
299             case SYSTEM_ACTION_ID_LOCK_SCREEN:
300                 labelId = R.string.accessibility_system_action_lock_screen_label;
301                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_LOCK_SCREEN;
302                 break;
303             case SYSTEM_ACTION_ID_TAKE_SCREENSHOT:
304                 labelId = R.string.accessibility_system_action_screenshot_label;
305                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_TAKE_SCREENSHOT;
306                 break;
307             case SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON:
308                 labelId = R.string.accessibility_system_action_on_screen_a11y_shortcut_label;
309                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_BUTTON;
310                 break;
311             case SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER:
312                 labelId =
313                         R.string.accessibility_system_action_on_screen_a11y_shortcut_chooser_label;
314                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER;
315                 break;
316             case SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT:
317                 labelId = R.string.accessibility_system_action_hardware_a11y_shortcut_label;
318                 intent = SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_SHORTCUT;
319                 break;
320             case SYSTEM_ACTION_ID_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE:
321                 labelId = R.string.accessibility_system_action_dismiss_notification_shade;
322                 intent = SystemActionsBroadcastReceiver
323                         .INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE;
324                 break;
325             default:
326                 return;
327         }
328         mA11yManager.registerSystemAction(createRemoteAction(labelId, intent), actionId);
329     }
330 
createRemoteAction(int labelId, String intent)331     private RemoteAction createRemoteAction(int labelId, String intent) {
332         // TODO(b/148087487): update the icon used below to a valid one
333         return new RemoteAction(
334                 Icon.createWithResource(mContext, R.drawable.ic_info),
335                 mContext.getString(labelId),
336                 mContext.getString(labelId),
337                 mReceiver.createPendingIntent(mContext, intent));
338     }
339 
340     /**
341      * Unregister a system action.
342      * @param actionId the action ID to unregister.
343      */
unregister(int actionId)344     public void unregister(int actionId) {
345         mA11yManager.unregisterSystemAction(actionId);
346     }
347 
handleBack()348     private void handleBack() {
349         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
350     }
351 
handleHome()352     private void handleHome() {
353         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
354     }
355 
sendDownAndUpKeyEvents(int keyCode)356     private void sendDownAndUpKeyEvents(int keyCode) {
357         final long downTime = SystemClock.uptimeMillis();
358         sendKeyEventIdentityCleared(keyCode, KeyEvent.ACTION_DOWN, downTime, downTime);
359         sendKeyEventIdentityCleared(
360                 keyCode, KeyEvent.ACTION_UP, downTime, SystemClock.uptimeMillis());
361     }
362 
sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time)363     private void sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time) {
364         KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
365                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
366                 InputDevice.SOURCE_KEYBOARD, null);
367         InputManager.getInstance()
368                 .injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
369         event.recycle();
370     }
371 
handleRecents()372     private void handleRecents() {
373         mRecentsOptional.ifPresent(Recents::toggleRecentApps);
374     }
375 
handleNotifications()376     private void handleNotifications() {
377         mStatusBarOptionalLazy.get().ifPresent(StatusBar::animateExpandNotificationsPanel);
378     }
379 
handleQuickSettings()380     private void handleQuickSettings() {
381         mStatusBarOptionalLazy.get().ifPresent(
382                 statusBar -> statusBar.animateExpandSettingsPanel(null));
383     }
384 
handlePowerDialog()385     private void handlePowerDialog() {
386         IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
387 
388         try {
389             windowManager.showGlobalActions();
390         } catch (RemoteException e) {
391             Log.e(TAG, "failed to display power dialog.");
392         }
393     }
394 
handleLockScreen()395     private void handleLockScreen() {
396         IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
397 
398         mContext.getSystemService(PowerManager.class).goToSleep(SystemClock.uptimeMillis(),
399                 PowerManager.GO_TO_SLEEP_REASON_ACCESSIBILITY, 0);
400         try {
401             windowManager.lockNow(null);
402         } catch (RemoteException e) {
403             Log.e(TAG, "failed to lock screen.");
404         }
405     }
406 
handleTakeScreenshot()407     private void handleTakeScreenshot() {
408         ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
409         screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN, true, true,
410                 SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
411     }
412 
handleAccessibilityButton()413     private void handleAccessibilityButton() {
414         AccessibilityManager.getInstance(mContext).notifyAccessibilityButtonClicked(
415                 Display.DEFAULT_DISPLAY);
416     }
417 
handleAccessibilityButtonChooser()418     private void handleAccessibilityButtonChooser() {
419         final Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
420         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
421         final String chooserClassName = AccessibilityButtonChooserActivity.class.getName();
422         intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
423         mContext.startActivityAsUser(intent, UserHandle.CURRENT);
424     }
425 
handleAccessibilityShortcut()426     private void handleAccessibilityShortcut() {
427         mA11yManager.performAccessibilityShortcut();
428     }
429 
handleAccessibilityDismissNotificationShade()430     private void handleAccessibilityDismissNotificationShade() {
431         mStatusBarOptionalLazy.get().ifPresent(
432                 statusBar -> statusBar.animateCollapsePanels(
433                         CommandQueue.FLAG_EXCLUDE_NONE, false /* force */));
434     }
435 
436     private class SystemActionsBroadcastReceiver extends BroadcastReceiver {
437         private static final String INTENT_ACTION_BACK = "SYSTEM_ACTION_BACK";
438         private static final String INTENT_ACTION_HOME = "SYSTEM_ACTION_HOME";
439         private static final String INTENT_ACTION_RECENTS = "SYSTEM_ACTION_RECENTS";
440         private static final String INTENT_ACTION_NOTIFICATIONS = "SYSTEM_ACTION_NOTIFICATIONS";
441         private static final String INTENT_ACTION_QUICK_SETTINGS = "SYSTEM_ACTION_QUICK_SETTINGS";
442         private static final String INTENT_ACTION_POWER_DIALOG = "SYSTEM_ACTION_POWER_DIALOG";
443         private static final String INTENT_ACTION_LOCK_SCREEN = "SYSTEM_ACTION_LOCK_SCREEN";
444         private static final String INTENT_ACTION_TAKE_SCREENSHOT = "SYSTEM_ACTION_TAKE_SCREENSHOT";
445         private static final String INTENT_ACTION_ACCESSIBILITY_BUTTON =
446                 "SYSTEM_ACTION_ACCESSIBILITY_BUTTON";
447         private static final String INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER =
448                 "SYSTEM_ACTION_ACCESSIBILITY_BUTTON_MENU";
449         private static final String INTENT_ACTION_ACCESSIBILITY_SHORTCUT =
450                 "SYSTEM_ACTION_ACCESSIBILITY_SHORTCUT";
451         private static final String INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE =
452                 "SYSTEM_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE";
453 
createPendingIntent(Context context, String intentAction)454         private PendingIntent createPendingIntent(Context context, String intentAction) {
455             switch (intentAction) {
456                 case INTENT_ACTION_BACK:
457                 case INTENT_ACTION_HOME:
458                 case INTENT_ACTION_RECENTS:
459                 case INTENT_ACTION_NOTIFICATIONS:
460                 case INTENT_ACTION_QUICK_SETTINGS:
461                 case INTENT_ACTION_POWER_DIALOG:
462                 case INTENT_ACTION_LOCK_SCREEN:
463                 case INTENT_ACTION_TAKE_SCREENSHOT:
464                 case INTENT_ACTION_ACCESSIBILITY_BUTTON:
465                 case INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER:
466                 case INTENT_ACTION_ACCESSIBILITY_SHORTCUT:
467                 case INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE: {
468                     Intent intent = new Intent(intentAction);
469                     intent.setPackage(context.getPackageName());
470                     return PendingIntent.getBroadcast(context, 0, intent,
471                             PendingIntent.FLAG_IMMUTABLE);
472                 }
473                 default:
474                     break;
475             }
476             return null;
477         }
478 
createIntentFilter()479         private IntentFilter createIntentFilter() {
480             IntentFilter intentFilter = new IntentFilter();
481             intentFilter.addAction(INTENT_ACTION_BACK);
482             intentFilter.addAction(INTENT_ACTION_HOME);
483             intentFilter.addAction(INTENT_ACTION_RECENTS);
484             intentFilter.addAction(INTENT_ACTION_NOTIFICATIONS);
485             intentFilter.addAction(INTENT_ACTION_QUICK_SETTINGS);
486             intentFilter.addAction(INTENT_ACTION_POWER_DIALOG);
487             intentFilter.addAction(INTENT_ACTION_LOCK_SCREEN);
488             intentFilter.addAction(INTENT_ACTION_TAKE_SCREENSHOT);
489             intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_BUTTON);
490             intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER);
491             intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_SHORTCUT);
492             intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE);
493             return intentFilter;
494         }
495 
496         @Override
onReceive(Context context, Intent intent)497         public void onReceive(Context context, Intent intent) {
498             String intentAction = intent.getAction();
499             switch (intentAction) {
500                 case INTENT_ACTION_BACK: {
501                     handleBack();
502                     break;
503                 }
504                 case INTENT_ACTION_HOME: {
505                     handleHome();
506                     break;
507                 }
508                 case INTENT_ACTION_RECENTS: {
509                     handleRecents();
510                     break;
511                 }
512                 case INTENT_ACTION_NOTIFICATIONS: {
513                     handleNotifications();
514                     break;
515                 }
516                 case INTENT_ACTION_QUICK_SETTINGS: {
517                     handleQuickSettings();
518                     break;
519                 }
520                 case INTENT_ACTION_POWER_DIALOG: {
521                     handlePowerDialog();
522                     break;
523                 }
524                 case INTENT_ACTION_LOCK_SCREEN: {
525                     handleLockScreen();
526                     break;
527                 }
528                 case INTENT_ACTION_TAKE_SCREENSHOT: {
529                     handleTakeScreenshot();
530                     break;
531                 }
532                 case INTENT_ACTION_ACCESSIBILITY_BUTTON: {
533                     handleAccessibilityButton();
534                     break;
535                 }
536                 case INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER: {
537                     handleAccessibilityButtonChooser();
538                     break;
539                 }
540                 case INTENT_ACTION_ACCESSIBILITY_SHORTCUT: {
541                     handleAccessibilityShortcut();
542                     break;
543                 }
544                 case INTENT_ACTION_ACCESSIBILITY_DISMISS_NOTIFICATION_SHADE: {
545                     handleAccessibilityDismissNotificationShade();
546                     break;
547                 }
548                 default:
549                     break;
550             }
551         }
552     }
553 }
554