1 /*
2  * Copyright (C) 2007 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.server.statusbar;
18 
19 import static android.Manifest.permission.CONTROL_DEVICE_STATE;
20 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
21 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
22 import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
23 import static android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE;
24 import static android.app.StatusBarManager.NAV_BAR_MODE_DEFAULT;
25 import static android.app.StatusBarManager.NAV_BAR_MODE_KIDS;
26 import static android.app.StatusBarManager.NavBarMode;
27 import static android.app.StatusBarManager.SessionFlags;
28 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
29 import static android.view.Display.DEFAULT_DISPLAY;
30 import static android.view.ViewRootImpl.CLIENT_TRANSIENT;
31 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
32 
33 import android.Manifest;
34 import android.annotation.NonNull;
35 import android.annotation.Nullable;
36 import android.annotation.RequiresPermission;
37 import android.annotation.TestApi;
38 import android.app.ActivityManager;
39 import android.app.ActivityManagerInternal;
40 import android.app.ActivityThread;
41 import android.app.ITransientNotificationCallback;
42 import android.app.Notification;
43 import android.app.StatusBarManager;
44 import android.app.compat.CompatChanges;
45 import android.compat.annotation.ChangeId;
46 import android.compat.annotation.EnabledAfter;
47 import android.compat.annotation.EnabledSince;
48 import android.content.ComponentName;
49 import android.content.Context;
50 import android.content.Intent;
51 import android.content.om.IOverlayManager;
52 import android.content.pm.PackageManager;
53 import android.content.pm.PackageManagerInternal;
54 import android.content.pm.ResolveInfo;
55 import android.graphics.drawable.Icon;
56 import android.hardware.biometrics.BiometricAuthenticator.Modality;
57 import android.hardware.biometrics.IBiometricContextListener;
58 import android.hardware.biometrics.IBiometricSysuiReceiver;
59 import android.hardware.biometrics.PromptInfo;
60 import android.hardware.display.DisplayManager;
61 import android.hardware.display.DisplayManager.DisplayListener;
62 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
63 import android.media.INearbyMediaDevicesProvider;
64 import android.media.MediaRoute2Info;
65 import android.net.Uri;
66 import android.os.Binder;
67 import android.os.Build;
68 import android.os.Bundle;
69 import android.os.Handler;
70 import android.os.IBinder;
71 import android.os.PowerManager;
72 import android.os.Process;
73 import android.os.RemoteException;
74 import android.os.ResultReceiver;
75 import android.os.ServiceManager;
76 import android.os.ShellCallback;
77 import android.os.UserHandle;
78 import android.provider.Settings;
79 import android.service.notification.NotificationStats;
80 import android.service.quicksettings.TileService;
81 import android.text.TextUtils;
82 import android.util.ArrayMap;
83 import android.util.IndentingPrintWriter;
84 import android.util.Pair;
85 import android.util.Slog;
86 import android.util.SparseArray;
87 import android.view.KeyEvent;
88 import android.view.WindowInsets;
89 import android.view.WindowInsets.Type.InsetsType;
90 import android.view.WindowInsetsController.Appearance;
91 import android.view.WindowInsetsController.Behavior;
92 import android.view.accessibility.Flags;
93 
94 import com.android.internal.R;
95 import com.android.internal.annotations.GuardedBy;
96 import com.android.internal.annotations.VisibleForTesting;
97 import com.android.internal.inputmethod.SoftInputShowHideReason;
98 import com.android.internal.logging.InstanceId;
99 import com.android.internal.os.TransferPipe;
100 import com.android.internal.statusbar.IAddTileResultCallback;
101 import com.android.internal.statusbar.ISessionListener;
102 import com.android.internal.statusbar.IStatusBar;
103 import com.android.internal.statusbar.IStatusBarService;
104 import com.android.internal.statusbar.IUndoMediaTransferCallback;
105 import com.android.internal.statusbar.LetterboxDetails;
106 import com.android.internal.statusbar.NotificationVisibility;
107 import com.android.internal.statusbar.RegisterStatusBarResult;
108 import com.android.internal.statusbar.StatusBarIcon;
109 import com.android.internal.util.DumpUtils;
110 import com.android.internal.util.GcUtils;
111 import com.android.internal.view.AppearanceRegion;
112 import com.android.server.LocalServices;
113 import com.android.server.UiThread;
114 import com.android.server.inputmethod.InputMethodManagerInternal;
115 import com.android.server.notification.NotificationDelegate;
116 import com.android.server.policy.GlobalActionsProvider;
117 import com.android.server.power.ShutdownCheckPoints;
118 import com.android.server.power.ShutdownThread;
119 import com.android.server.wm.ActivityTaskManagerInternal;
120 
121 import java.io.FileDescriptor;
122 import java.io.PrintWriter;
123 import java.util.ArrayList;
124 import java.util.concurrent.TimeUnit;
125 
126 /**
127  * A note on locking:  We rely on the fact that calls onto mBar are oneway or
128  * if they are local, that they just enqueue messages to not deadlock.
129  */
130 public class StatusBarManagerService extends IStatusBarService.Stub implements DisplayListener {
131     private static final String TAG = "StatusBarManagerService";
132     private static final boolean SPEW = false;
133 
134     /**
135      * Apps targeting {@code Build.VERSION_CODES.S} or higher need {@link
136      * android.Manifest.permission#STATUS_BAR} permission to collapse the status bar panels due to
137      * security reasons.
138      *
139      * This was being exploited by malware to prevent the user from accessing critical
140      * notifications.
141      */
142     @ChangeId
143     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
144     private static final long LOCK_DOWN_COLLAPSE_STATUS_BAR = 173031413L;
145 
146     /**
147      * In apps targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher, calling
148      * {@link android.service.quicksettings.TileService#requestListeningState} will check that the
149      * calling package (uid) and the package of the target {@link android.content.ComponentName}
150      * match. It'll also make sure that the context used can take actions on behalf of the current
151      * user.
152      */
153     @ChangeId
154     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
155     static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L;
156 
157     /**
158      * @hide
159      */
160     @ChangeId
161     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
162     static final long REQUEST_LISTENING_OTHER_USER_NOOP = 242194868L;
163 
164     private final Context mContext;
165 
166     private final Handler mHandler = new Handler();
167     private NotificationDelegate mNotificationDelegate;
168     private volatile IStatusBar mBar;
169     private final ArrayMap<String, StatusBarIcon> mIcons = new ArrayMap<>();
170 
171     // for disabling the status bar
172     private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
173     private GlobalActionsProvider.GlobalActionsListener mGlobalActionListener;
174     private final IBinder mSysUiVisToken = new Binder();
175 
176     private final Object mLock = new Object();
177     private final DeathRecipient mDeathRecipient = new DeathRecipient();
178     private final ActivityManagerInternal mActivityManagerInternal;
179     private final ActivityTaskManagerInternal mActivityTaskManager;
180     private final PackageManagerInternal mPackageManagerInternal;
181     private final SessionMonitor mSessionMonitor;
182     private int mCurrentUserId;
183     private boolean mTracingEnabled;
184     private int mLastSystemKey = -1;
185 
186     private final TileRequestTracker mTileRequestTracker;
187 
188     private final SparseArray<UiState> mDisplayUiState = new SparseArray<>();
189     @GuardedBy("mLock")
190     private IUdfpsRefreshRateRequestCallback mUdfpsRefreshRateRequestCallback;
191     @GuardedBy("mLock")
192     private IBiometricContextListener mBiometricContextListener;
193 
194     @GuardedBy("mCurrentRequestAddTilePackages")
195     private final ArrayMap<String, Long> mCurrentRequestAddTilePackages = new ArrayMap<>();
196     private static final long REQUEST_TIME_OUT = TimeUnit.MINUTES.toNanos(5);
197 
198     private IOverlayManager mOverlayManager;
199 
200     private class DeathRecipient implements IBinder.DeathRecipient {
binderDied()201         public void binderDied() {
202             mBar.asBinder().unlinkToDeath(this,0);
203             mBar = null;
204             notifyBarAttachChanged();
205         }
206 
linkToDeath()207         public void linkToDeath() {
208             try {
209                 mBar.asBinder().linkToDeath(mDeathRecipient,0);
210             } catch (RemoteException e) {
211                 Slog.e(TAG,"Unable to register Death Recipient for status bar", e);
212             }
213         }
214 
215     }
216 
217     private class DisableRecord implements IBinder.DeathRecipient {
218         int userId;
219         String pkg;
220         int what1;
221         int what2;
222         IBinder token;
223 
DisableRecord(int userId, IBinder token)224         public DisableRecord(int userId, IBinder token) {
225             this.userId = userId;
226             this.token = token;
227             try {
228                 token.linkToDeath(this, 0);
229             } catch (RemoteException re) {
230                 // Give up
231             }
232         }
233 
234         @Override
binderDied()235         public void binderDied() {
236             Slog.i(TAG, "binder died for pkg=" + pkg);
237             disableForUser(0, token, pkg, userId);
238             disable2ForUser(0, token, pkg, userId);
239             token.unlinkToDeath(this, 0);
240         }
241 
setFlags(int what, int which, String pkg)242         public void setFlags(int what, int which, String pkg) {
243             switch (which) {
244                 case 1:
245                     what1 = what;
246                     break;
247                 case 2:
248                     what2 = what;
249                     break;
250                 default:
251                     Slog.w(TAG, "Can't set unsupported disable flag " + which
252                             + ": 0x" + Integer.toHexString(what));
253                     break;
254             }
255             this.pkg = pkg;
256         }
257 
getFlags(int which)258         public int getFlags(int which) {
259             switch (which) {
260                 case 1: return what1;
261                 case 2: return what2;
262                 default:
263                     Slog.w(TAG, "Can't get unsupported disable flag " + which);
264                     return 0;
265             }
266         }
267 
isEmpty()268         public boolean isEmpty() {
269             return what1 == 0 && what2 == 0;
270         }
271 
272         @Override
toString()273         public String toString() {
274             return String.format("userId=%d what1=0x%08X what2=0x%08X pkg=%s token=%s",
275                     userId, what1, what2, pkg, token);
276         }
277     }
278 
279     /**
280      * Construct the service
281      */
StatusBarManagerService(Context context)282     public StatusBarManagerService(Context context) {
283         mContext = context;
284 
285         LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
286 
287         // We always have a default display.
288         final UiState state = new UiState();
289         mDisplayUiState.put(DEFAULT_DISPLAY, state);
290 
291         final DisplayManager displayManager =
292                 (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
293         displayManager.registerDisplayListener(this, mHandler);
294         mActivityTaskManager = LocalServices.getService(ActivityTaskManagerInternal.class);
295         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
296         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
297 
298         mTileRequestTracker = new TileRequestTracker(mContext);
299         mSessionMonitor = new SessionMonitor(mContext);
300     }
301 
302     /**
303      * Publish the {@link GlobalActionsProvider}.
304      */
305     // TODO(b/259420401): investigate if we can extract GlobalActionsProvider to its own system
306     // service.
publishGlobalActionsProvider()307     public void publishGlobalActionsProvider() {
308         if (LocalServices.getService(GlobalActionsProvider.class) == null) {
309             LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);
310         }
311     }
312 
getOverlayManager()313     private IOverlayManager getOverlayManager() {
314         // No need to synchronize; worst-case scenario it will be fetched twice.
315         if (mOverlayManager == null) {
316             mOverlayManager = IOverlayManager.Stub.asInterface(
317                     ServiceManager.getService(Context.OVERLAY_SERVICE));
318             if (mOverlayManager == null) {
319                 Slog.w("StatusBarManager", "warning: no OVERLAY_SERVICE");
320             }
321         }
322         return mOverlayManager;
323     }
324 
325     @Override
onDisplayAdded(int displayId)326     public void onDisplayAdded(int displayId) {}
327 
328     @Override
onDisplayRemoved(int displayId)329     public void onDisplayRemoved(int displayId) {
330         synchronized (mLock) {
331             mDisplayUiState.remove(displayId);
332         }
333     }
334 
335     @Override
onDisplayChanged(int displayId)336     public void onDisplayChanged(int displayId) {}
337 
338     /**
339      * Private API used by NotificationManagerService.
340      */
341     private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {
342         private boolean mNotificationLightOn;
343 
344         @Override
345         public void setNotificationDelegate(NotificationDelegate delegate) {
346             mNotificationDelegate = delegate;
347         }
348 
349         @Override
350         public void showScreenPinningRequest(int taskId) {
351             IStatusBar bar = mBar;
352             if (bar != null) {
353                 try {
354                     bar.showScreenPinningRequest(taskId);
355                 } catch (RemoteException e) {
356                 }
357             }
358         }
359 
360         @Override
361         public void showAssistDisclosure() {
362             IStatusBar bar = mBar;
363             if (bar != null) {
364                 try {
365                     bar.showAssistDisclosure();
366                 } catch (RemoteException e) {
367                 }
368             }
369         }
370 
371         @Override
372         public void startAssist(Bundle args) {
373             IStatusBar bar = mBar;
374             if (bar != null) {
375                 try {
376                     bar.startAssist(args);
377                 } catch (RemoteException e) {
378                 }
379             }
380         }
381 
382         @Override
383         public void onCameraLaunchGestureDetected(int source) {
384             IStatusBar bar = mBar;
385             if (bar != null) {
386                 try {
387                     bar.onCameraLaunchGestureDetected(source);
388                 } catch (RemoteException e) {
389                 }
390             }
391         }
392 
393         /**
394          * Notifies the status bar that a Emergency Action launch gesture has been detected.
395          *
396          * TODO (b/169175022) Update method name and docs when feature name is locked.
397          */
398         @Override
399         public void onEmergencyActionLaunchGestureDetected() {
400             if (SPEW) Slog.d(TAG, "Launching emergency action");
401             IStatusBar bar = mBar;
402             if (bar != null) {
403                 try {
404                     bar.onEmergencyActionLaunchGestureDetected();
405                 } catch (RemoteException e) {
406                     if (SPEW) Slog.d(TAG, "Failed to launch emergency action");
407                 }
408             }
409         }
410 
411         @Override
412         public void setDisableFlags(int displayId, int flags, String cause) {
413             StatusBarManagerService.this.setDisableFlags(displayId, flags, cause);
414         }
415 
416         @Override
417         public void toggleSplitScreen() {
418             enforceStatusBarService();
419             IStatusBar bar = mBar;
420             if (bar != null) {
421                 try {
422                     bar.toggleSplitScreen();
423                 } catch (RemoteException ex) {}
424             }
425         }
426 
427         @Override
428         public void appTransitionFinished(int displayId) {
429             enforceStatusBarService();
430             IStatusBar bar = mBar;
431             if (bar != null) {
432                 try {
433                     bar.appTransitionFinished(displayId);
434                 } catch (RemoteException ex) {}
435             }
436         }
437 
438         @Override
439         public void toggleTaskbar() {
440             IStatusBar bar = mBar;
441             if (bar != null) {
442                 try {
443                     bar.toggleTaskbar();
444                 } catch (RemoteException ex) {}
445             }
446         }
447 
448         @Override
449         public void toggleRecentApps() {
450             IStatusBar bar = mBar;
451             if (bar != null) {
452                 try {
453                     bar.toggleRecentApps();
454                 } catch (RemoteException ex) {}
455             }
456         }
457 
458         @Override
459         public void setCurrentUser(int newUserId) {
460             if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
461             mCurrentUserId = newUserId;
462         }
463 
464 
465         @Override
466         public void preloadRecentApps() {
467             IStatusBar bar = mBar;
468             if (bar != null) {
469                 try {
470                     bar.preloadRecentApps();
471                 } catch (RemoteException ex) {}
472             }
473         }
474 
475         @Override
476         public void cancelPreloadRecentApps() {
477             IStatusBar bar = mBar;
478             if (bar != null) {
479                 try {
480                     bar.cancelPreloadRecentApps();
481                 } catch (RemoteException ex) {}
482             }
483         }
484 
485         @Override
486         public void showRecentApps(boolean triggeredFromAltTab) {
487             IStatusBar bar = mBar;
488             if (bar != null) {
489                 try {
490                     bar.showRecentApps(triggeredFromAltTab);
491                 } catch (RemoteException ex) {}
492             }
493         }
494 
495         @Override
496         public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
497             IStatusBar bar = mBar;
498             if (bar != null) {
499                 try {
500                     bar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey);
501                 } catch (RemoteException ex) {}
502             }
503         }
504 
505         @Override
506         public void collapsePanels() {
507             IStatusBar bar = mBar;
508             if (bar != null) {
509                 try {
510                     bar.animateCollapsePanels();
511                 } catch (RemoteException ex) {
512                 }
513             }
514         }
515 
516         @Override
517         public void dismissKeyboardShortcutsMenu() {
518             IStatusBar bar = mBar;
519             if (bar != null) {
520                 try {
521                     bar.dismissKeyboardShortcutsMenu();
522                 } catch (RemoteException ex) {}
523             }
524         }
525 
526         @Override
527         public void toggleKeyboardShortcutsMenu(int deviceId) {
528             IStatusBar bar = mBar;
529             if (bar != null) {
530                 try {
531                     bar.toggleKeyboardShortcutsMenu(deviceId);
532                 } catch (RemoteException ex) {}
533             }
534         }
535 
536         @Override
537         public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
538                 boolean showImeSwitcher) {
539             StatusBarManagerService.this.setImeWindowStatus(displayId, token, vis, backDisposition,
540                     showImeSwitcher);
541         }
542 
543         @Override
544         public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
545                 String contentDescription) {
546             StatusBarManagerService.this.setIcon(slot, iconPackage, iconId, iconLevel,
547                     contentDescription);
548         }
549 
550         @Override
551         public void setIconVisibility(String slot, boolean visibility) {
552             StatusBarManagerService.this.setIconVisibility(slot, visibility);
553         }
554 
555         @Override
556         public void showChargingAnimation(int batteryLevel) {
557             IStatusBar bar = mBar;
558             if (bar != null) {
559                 try {
560                     bar.showWirelessChargingAnimation(batteryLevel);
561                 } catch (RemoteException ex){
562                 }
563             }
564         }
565 
566         @Override
567         public void showPictureInPictureMenu() {
568             IStatusBar bar = mBar;
569             if (bar != null) {
570                 try {
571                     mBar.showPictureInPictureMenu();
572                 } catch (RemoteException ex) {}
573             }
574         }
575 
576         @Override
577         public void setWindowState(int displayId, int window, int state) {
578             IStatusBar bar = mBar;
579             if (bar != null) {
580                 try {
581                     bar.setWindowState(displayId, window, state);
582                 } catch (RemoteException ex) {}
583             }
584         }
585 
586         @Override
587         public void appTransitionPending(int displayId) {
588             IStatusBar bar = mBar;
589             if (bar != null) {
590                 try {
591                     bar.appTransitionPending(displayId);
592                 } catch (RemoteException ex) {}
593             }
594         }
595 
596         @Override
597         public void appTransitionCancelled(int displayId) {
598             IStatusBar bar = mBar;
599             if (bar != null) {
600                 try {
601                     bar.appTransitionCancelled(displayId);
602                 } catch (RemoteException ex) {}
603             }
604         }
605 
606         @Override
607         public void appTransitionStarting(int displayId, long statusBarAnimationsStartTime,
608                 long statusBarAnimationsDuration) {
609             IStatusBar bar = mBar;
610             if (bar != null) {
611                 try {
612                     bar.appTransitionStarting(
613                             displayId, statusBarAnimationsStartTime, statusBarAnimationsDuration);
614                 } catch (RemoteException ex) {}
615             }
616         }
617 
618         @Override
619         public void setTopAppHidesStatusBar(boolean hidesStatusBar) {
620             IStatusBar bar = mBar;
621             if (bar != null) {
622                 try {
623                     bar.setTopAppHidesStatusBar(hidesStatusBar);
624                 } catch (RemoteException ex) {}
625             }
626         }
627 
628         @Override
629         public boolean showShutdownUi(boolean isReboot, String reason) {
630             if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) {
631                 return false;
632             }
633             IStatusBar bar = mBar;
634             if (bar != null) {
635                 try {
636                     bar.showShutdownUi(isReboot, reason);
637                     return true;
638                 } catch (RemoteException ex) {}
639             }
640             return false;
641         }
642 
643         @Override
644         public void confirmImmersivePrompt() {
645             if (mBar == null) {
646                 return;
647             }
648             try {
649                 mBar.confirmImmersivePrompt();
650             } catch (RemoteException ex) {
651             }
652         }
653 
654         @Override
655         public void immersiveModeChanged(int rootDisplayAreaId, boolean isImmersiveMode) {
656             if (mBar == null) {
657                 return;
658             }
659             if (!CLIENT_TRANSIENT) {
660                 // Only call from here when the client transient is not enabled.
661                 try {
662                     mBar.immersiveModeChanged(rootDisplayAreaId, isImmersiveMode);
663                 } catch (RemoteException ex) {
664                 }
665             }
666         }
667 
668         // TODO(b/118592525): support it per display if necessary.
669         @Override
670         public void onProposedRotationChanged(int rotation, boolean isValid) {
671             if (mBar != null){
672                 try {
673                     mBar.onProposedRotationChanged(rotation, isValid);
674                 } catch (RemoteException ex) {}
675             }
676         }
677 
678         @Override
679         public void onDisplayReady(int displayId) {
680             IStatusBar bar = mBar;
681             if (bar != null) {
682                 try {
683                     bar.onDisplayReady(displayId);
684                 } catch (RemoteException ex) {}
685             }
686         }
687 
688         @Override
689         public void onRecentsAnimationStateChanged(boolean running) {
690             IStatusBar bar = mBar;
691             if (bar != null) {
692                 try {
693                     bar.onRecentsAnimationStateChanged(running);
694                 } catch (RemoteException ex) {}
695             }
696 
697         }
698 
699         @Override
700         public void onSystemBarAttributesChanged(int displayId, @Appearance int appearance,
701                 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme,
702                 @Behavior int behavior, @InsetsType int requestedVisibleTypes,
703                 String packageName, LetterboxDetails[] letterboxDetails) {
704             getUiState(displayId).setBarAttributes(appearance, appearanceRegions,
705                     navbarColorManagedByIme, behavior, requestedVisibleTypes, packageName,
706                     letterboxDetails);
707             IStatusBar bar = mBar;
708             if (bar != null) {
709                 try {
710                     bar.onSystemBarAttributesChanged(displayId, appearance, appearanceRegions,
711                             navbarColorManagedByIme, behavior, requestedVisibleTypes, packageName,
712                             letterboxDetails);
713                 } catch (RemoteException ex) { }
714             }
715         }
716 
717         @Override
718         public void showTransient(int displayId, @InsetsType int types,
719                 boolean isGestureOnSystemBar) {
720             getUiState(displayId).showTransient(types);
721             IStatusBar bar = mBar;
722             if (bar != null) {
723                 try {
724                     bar.showTransient(displayId, types, isGestureOnSystemBar);
725                 } catch (RemoteException ex) { }
726             }
727         }
728 
729         @Override
730         public void abortTransient(int displayId, @InsetsType int types) {
731             getUiState(displayId).clearTransient(types);
732             IStatusBar bar = mBar;
733             if (bar != null) {
734                 try {
735                     bar.abortTransient(displayId, types);
736                 } catch (RemoteException ex) { }
737             }
738         }
739 
740         @Override
741         public void showToast(int uid, String packageName, IBinder token, CharSequence text,
742                 IBinder windowToken, int duration,
743                 @Nullable ITransientNotificationCallback callback, int displayId) {
744             IStatusBar bar = mBar;
745             if (bar != null) {
746                 try {
747                     bar.showToast(uid, packageName, token, text, windowToken, duration, callback,
748                             displayId);
749                 } catch (RemoteException ex) { }
750             }
751         }
752 
753         @Override
754         public void hideToast(String packageName, IBinder token) {
755             IStatusBar bar = mBar;
756             if (bar != null) {
757                 try {
758                     bar.hideToast(packageName, token);
759                 } catch (RemoteException ex) { }
760             }
761         }
762 
763         @Override
764         public boolean requestMagnificationConnection(boolean request) {
765             IStatusBar bar = mBar;
766             if (bar != null) {
767                 try {
768                     bar.requestMagnificationConnection(request);
769                     return true;
770                 } catch (RemoteException ex) { }
771             }
772             return false;
773         }
774 
775         @Override
776         public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
777             IStatusBar bar = mBar;
778             if (bar != null) {
779                 try {
780                     bar.setNavigationBarLumaSamplingEnabled(displayId, enable);
781                 } catch (RemoteException ex) { }
782             }
783         }
784 
785         @Override
786         public void setUdfpsRefreshRateCallback(IUdfpsRefreshRateRequestCallback callback) {
787             synchronized (mLock) {
788                 mUdfpsRefreshRateRequestCallback = callback;
789             }
790             IStatusBar bar = mBar;
791             if (bar != null) {
792                 try {
793                     bar.setUdfpsRefreshRateCallback(callback);
794                 } catch (RemoteException ex) { }
795             }
796         }
797 
798         @Override
799         public void showRearDisplayDialog(int currentBaseState) {
800             IStatusBar bar = mBar;
801             if (bar != null) {
802                 try {
803                     bar.showRearDisplayDialog(currentBaseState);
804                 } catch (RemoteException ex) { }
805             }
806         }
807 
808         @Override
809         public void moveFocusedTaskToFullscreen(int displayId) {
810             IStatusBar bar = mBar;
811             if (bar != null) {
812                 try {
813                     bar.moveFocusedTaskToFullscreen(displayId);
814                 } catch (RemoteException ex) { }
815             }
816         }
817 
818         @Override
819         public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
820             IStatusBar bar = mBar;
821             if (bar != null) {
822                 try {
823                     bar.moveFocusedTaskToStageSplit(displayId, leftOrTop);
824                 } catch (RemoteException ex) { }
825             }
826         }
827 
828         @Override
829         public void setSplitscreenFocus(boolean leftOrTop) {
830             IStatusBar bar = mBar;
831             if (bar != null) {
832                 try {
833                     bar.setSplitscreenFocus(leftOrTop);
834                 } catch (RemoteException ex) { }
835             }
836         }
837 
838         @Override
839         public void moveFocusedTaskToDesktop(int displayId) {
840             IStatusBar bar = mBar;
841             if (bar != null) {
842                 try {
843                     bar.moveFocusedTaskToDesktop(displayId);
844                 } catch (RemoteException ex) { }
845             }
846         }
847 
848         @Override
849         public void showMediaOutputSwitcher(String targetPackageName, UserHandle targetUserHandle) {
850             IStatusBar bar = mBar;
851             if (bar != null) {
852                 try {
853                     bar.showMediaOutputSwitcher(targetPackageName, targetUserHandle);
854                 } catch (RemoteException ex) {
855                 }
856             }
857         }
858 
859         @Override
860         public void addQsTileToFrontOrEnd(ComponentName tile, boolean end) {
861             if (Flags.a11yQsShortcut()) {
862                 StatusBarManagerService.this.addQsTileToFrontOrEnd(tile, end);
863             }
864         }
865 
866         @Override
867         public void removeQsTile(ComponentName tile) {
868             if (Flags.a11yQsShortcut()) {
869                 StatusBarManagerService.this.remTile(tile);
870             }
871         }
872     };
873 
874     private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
875         @Override
876         public boolean isGlobalActionsDisabled() {
877             // TODO(b/118592525): support global actions for multi-display.
878             final int disabled2 = mDisplayUiState.get(DEFAULT_DISPLAY).getDisabled2();
879             return (disabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;
880         }
881 
882         @Override
883         public void setGlobalActionsListener(GlobalActionsProvider.GlobalActionsListener listener) {
884             mGlobalActionListener = listener;
885             mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);
886         }
887 
888         @Override
889         public void showGlobalActions() {
890             IStatusBar bar = mBar;
891             if (bar != null) {
892                 try {
893                     bar.showGlobalActionsMenu();
894                 } catch (RemoteException ex) {}
895             }
896         }
897     };
898 
899     /**
900      * Returns true if the target disable flag (target2) is set
901      */
isDisable2FlagSet(int target2)902     private boolean isDisable2FlagSet(int target2) {
903         final int disabled2 = mDisplayUiState.get(DEFAULT_DISPLAY).getDisabled2();
904         return ((disabled2 & target2) == target2);
905     }
906 
907     // ================================================================================
908     // From IStatusBarService
909     // ================================================================================
910 
911     @Override
expandNotificationsPanel()912     public void expandNotificationsPanel() {
913         enforceExpandStatusBar();
914 
915         if (isDisable2FlagSet(DISABLE2_NOTIFICATION_SHADE)) {
916             return;
917         }
918 
919         if (mBar != null) {
920             try {
921                 mBar.animateExpandNotificationsPanel();
922             } catch (RemoteException ex) {
923             }
924         }
925     }
926 
927     @Override
collapsePanels()928     public void collapsePanels() {
929         if (!checkCanCollapseStatusBar("collapsePanels")) {
930             return;
931         }
932 
933         if (mBar != null) {
934             try {
935                 mBar.animateCollapsePanels();
936             } catch (RemoteException ex) {
937             }
938         }
939     }
940 
941     @Override
togglePanel()942     public void togglePanel() {
943         if (!checkCanCollapseStatusBar("togglePanel")) {
944             return;
945         }
946 
947         if (isDisable2FlagSet(DISABLE2_NOTIFICATION_SHADE)) {
948             return;
949         }
950 
951         if (mBar != null) {
952             try {
953                 mBar.toggleNotificationsPanel();
954             } catch (RemoteException ex) {
955             }
956         }
957     }
958 
959     @Override
expandSettingsPanel(String subPanel)960     public void expandSettingsPanel(String subPanel) {
961         enforceExpandStatusBar();
962 
963         if (mBar != null) {
964             try {
965                 mBar.animateExpandSettingsPanel(subPanel);
966             } catch (RemoteException ex) {
967             }
968         }
969     }
970 
addTile(ComponentName component)971     public void addTile(ComponentName component) {
972         if (Flags.a11yQsShortcut()) {
973             addQsTileToFrontOrEnd(component, false);
974         } else {
975             enforceStatusBarOrShell();
976 
977             if (mBar != null) {
978                 try {
979                     mBar.addQsTile(component);
980                 } catch (RemoteException ex) {
981                 }
982             }
983         }
984     }
985 
addQsTileToFrontOrEnd(ComponentName tile, boolean end)986     private void addQsTileToFrontOrEnd(ComponentName tile, boolean end) {
987         enforceStatusBarOrShell();
988 
989         if (mBar != null) {
990             try {
991                 mBar.addQsTileToFrontOrEnd(tile, end);
992             } catch (RemoteException ex) {
993             }
994         }
995     }
996 
remTile(ComponentName component)997     public void remTile(ComponentName component) {
998         enforceStatusBarOrShell();
999 
1000         if (mBar != null) {
1001             try {
1002                 mBar.remQsTile(component);
1003             } catch (RemoteException ex) {
1004             }
1005         }
1006     }
1007 
setTiles(String tiles)1008     public void setTiles(String tiles) {
1009         enforceStatusBarOrShell();
1010 
1011         if (mBar != null) {
1012             try {
1013                 mBar.setQsTiles(tiles.split(","));
1014             } catch (RemoteException ex) {
1015             }
1016         }
1017     }
1018 
clickTile(ComponentName component)1019     public void clickTile(ComponentName component) {
1020         enforceStatusBarOrShell();
1021 
1022         if (mBar != null) {
1023             try {
1024                 mBar.clickQsTile(component);
1025             } catch (RemoteException ex) {
1026             }
1027         }
1028     }
1029 
1030     @Override
handleSystemKey(KeyEvent key)1031     public void handleSystemKey(KeyEvent key) throws RemoteException {
1032         if (!checkCanCollapseStatusBar("handleSystemKey")) {
1033             return;
1034         }
1035 
1036         mLastSystemKey = key.getKeyCode();
1037 
1038         if (mBar != null) {
1039             try {
1040                 mBar.handleSystemKey(key);
1041             } catch (RemoteException ex) {
1042             }
1043         }
1044     }
1045 
1046     @Override
1047     @TestApi
getLastSystemKey()1048     public int getLastSystemKey() {
1049         enforceStatusBar();
1050 
1051         return mLastSystemKey;
1052     }
1053 
1054     @Override
showPinningEnterExitToast(boolean entering)1055     public void showPinningEnterExitToast(boolean entering) throws RemoteException {
1056         if (mBar != null) {
1057             try {
1058                 mBar.showPinningEnterExitToast(entering);
1059             } catch (RemoteException ex) {
1060             }
1061         }
1062     }
1063 
1064     @Override
showPinningEscapeToast()1065     public void showPinningEscapeToast() throws RemoteException {
1066         if (mBar != null) {
1067             try {
1068                 mBar.showPinningEscapeToast();
1069             } catch (RemoteException ex) {
1070             }
1071         }
1072     }
1073 
1074     @Override
showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver, int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, int userId, long operationId, String opPackageName, long requestId)1075     public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver,
1076             int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,
1077             int userId, long operationId, String opPackageName, long requestId) {
1078         enforceBiometricDialog();
1079         if (mBar != null) {
1080             try {
1081                 mBar.showAuthenticationDialog(promptInfo, receiver, sensorIds, credentialAllowed,
1082                         requireConfirmation, userId, operationId, opPackageName, requestId);
1083             } catch (RemoteException ex) {
1084             }
1085         }
1086     }
1087 
1088     @Override
onBiometricAuthenticated(@odality int modality)1089     public void onBiometricAuthenticated(@Modality int modality) {
1090         enforceBiometricDialog();
1091         if (mBar != null) {
1092             try {
1093                 mBar.onBiometricAuthenticated(modality);
1094             } catch (RemoteException ex) {
1095             }
1096         }
1097     }
1098 
1099     @Override
onBiometricHelp(@odality int modality, String message)1100     public void onBiometricHelp(@Modality int modality, String message) {
1101         enforceBiometricDialog();
1102         if (mBar != null) {
1103             try {
1104                 mBar.onBiometricHelp(modality, message);
1105             } catch (RemoteException ex) {
1106             }
1107         }
1108     }
1109 
1110     @Override
onBiometricError(int modality, int error, int vendorCode)1111     public void onBiometricError(int modality, int error, int vendorCode) {
1112         enforceBiometricDialog();
1113         if (mBar != null) {
1114             try {
1115                 mBar.onBiometricError(modality, error, vendorCode);
1116             } catch (RemoteException ex) {
1117             }
1118         }
1119     }
1120 
1121     @Override
hideAuthenticationDialog(long requestId)1122     public void hideAuthenticationDialog(long requestId) {
1123         enforceBiometricDialog();
1124         if (mBar != null) {
1125             try {
1126                 mBar.hideAuthenticationDialog(requestId);
1127             } catch (RemoteException ex) {
1128             }
1129         }
1130     }
1131 
1132     @Override
setBiometicContextListener(IBiometricContextListener listener)1133     public void setBiometicContextListener(IBiometricContextListener listener) {
1134         enforceStatusBarService();
1135         synchronized (mLock) {
1136             mBiometricContextListener = listener;
1137         }
1138         if (mBar != null) {
1139             try {
1140                 mBar.setBiometicContextListener(listener);
1141             } catch (RemoteException ex) {
1142             }
1143         }
1144     }
1145 
1146     @Override
setUdfpsRefreshRateCallback(IUdfpsRefreshRateRequestCallback callback)1147     public void setUdfpsRefreshRateCallback(IUdfpsRefreshRateRequestCallback callback) {
1148         enforceStatusBarService();
1149         if (mBar != null) {
1150             try {
1151                 mBar.setUdfpsRefreshRateCallback(callback);
1152             } catch (RemoteException ex) {
1153             }
1154         }
1155     }
1156 
1157     @Override
startTracing()1158     public void startTracing() {
1159         if (mBar != null) {
1160             try {
1161                 mBar.startTracing();
1162                 mTracingEnabled = true;
1163             } catch (RemoteException ex) {
1164             }
1165         }
1166     }
1167 
1168     @Override
stopTracing()1169     public void stopTracing() {
1170         if (mBar != null) {
1171             try {
1172                 mTracingEnabled = false;
1173                 mBar.stopTracing();
1174             } catch (RemoteException ex) {}
1175         }
1176     }
1177 
1178     @Override
isTracing()1179     public boolean isTracing() {
1180         return mTracingEnabled;
1181     }
1182 
1183     // TODO(b/117478341): make it aware of multi-display if needed.
1184     @Override
disable(int what, IBinder token, String pkg)1185     public void disable(int what, IBinder token, String pkg) {
1186         disableForUser(what, token, pkg, mCurrentUserId);
1187     }
1188 
1189     // TODO(b/117478341): make it aware of multi-display if needed.
1190     @Override
disableForUser(int what, IBinder token, String pkg, int userId)1191     public void disableForUser(int what, IBinder token, String pkg, int userId) {
1192         enforceStatusBar();
1193 
1194         synchronized (mLock) {
1195             disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, 1);
1196         }
1197     }
1198 
1199     // TODO(b/117478341): make it aware of multi-display if needed.
1200     /**
1201      * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags.
1202      * To re-enable everything, pass {@link #DISABLE2_NONE}.
1203      *
1204      * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags.
1205      */
1206     @Override
disable2(int what, IBinder token, String pkg)1207     public void disable2(int what, IBinder token, String pkg) {
1208         disable2ForUser(what, token, pkg, mCurrentUserId);
1209     }
1210 
1211     // TODO(b/117478341): make it aware of multi-display if needed.
1212     /**
1213      * Disable additional status bar features for a given user. Pass the bitwise-or of the
1214      * DISABLE2_* flags. To re-enable everything, pass {@link #DISABLE_NONE}.
1215      *
1216      * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags.
1217      */
1218     @Override
disable2ForUser(int what, IBinder token, String pkg, int userId)1219     public void disable2ForUser(int what, IBinder token, String pkg, int userId) {
1220         enforceStatusBar();
1221 
1222         synchronized (mLock) {
1223             disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, 2);
1224         }
1225     }
1226 
disableLocked(int displayId, int userId, int what, IBinder token, String pkg, int whichFlag)1227     private void disableLocked(int displayId, int userId, int what, IBinder token, String pkg,
1228             int whichFlag) {
1229         // It's important that the the callback and the call to mBar get done
1230         // in the same order when multiple threads are calling this function
1231         // so they are paired correctly.  The messages on the handler will be
1232         // handled in the order they were enqueued, but will be outside the lock.
1233         manageDisableListLocked(userId, what, token, pkg, whichFlag);
1234 
1235         // Ensure state for the current user is applied, even if passed a non-current user.
1236         final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1);
1237         final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2);
1238         final UiState state = getUiState(displayId);
1239         if (!state.disableEquals(net1, net2)) {
1240             state.setDisabled(net1, net2);
1241             mHandler.post(() -> mNotificationDelegate.onSetDisabled(net1));
1242             IStatusBar bar = mBar;
1243             if (bar != null) {
1244                 try {
1245                     bar.disable(displayId, net1, net2);
1246                 } catch (RemoteException ex) {
1247                 }
1248             }
1249         }
1250     }
1251 
1252     /**
1253      * Get the currently applied disable flags, in the form of one Pair<Integer, Integer>.
1254      *
1255      * @return pair of disable flags in the form of (disabled1, disabled2), where (0, 0) indicates
1256      * no flags are set for this token.
1257      */
1258     @Override
getDisableFlags(IBinder token, int userId)1259     public int[] getDisableFlags(IBinder token, int userId) {
1260         enforceStatusBar();
1261 
1262         int disable1 = 0;
1263         int disable2 = 0;
1264         synchronized (mLock) {
1265             // Find a matching record if it exists
1266             DisableRecord record = findMatchingRecordLocked(token, userId).second;
1267             if (record != null) {
1268                 disable1 = record.what1;
1269                 disable2 = record.what2;
1270             }
1271         }
1272 
1273         return new int[] {disable1, disable2};
1274     }
1275 
runGcForTest()1276     void runGcForTest() {
1277         if (!Build.IS_DEBUGGABLE) {
1278             throw new SecurityException("runGcForTest requires a debuggable build");
1279         }
1280 
1281         // Gc the system along the way
1282         GcUtils.runGcAndFinalizersSync();
1283 
1284         if (mBar != null) {
1285             try {
1286                 mBar.runGcForTest();
1287             } catch (RemoteException ex) {
1288             }
1289         }
1290     }
1291 
1292     @Override
setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription)1293     public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
1294             String contentDescription) {
1295         enforceStatusBar();
1296 
1297         synchronized (mIcons) {
1298             StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.SYSTEM, iconId,
1299                     iconLevel, 0, contentDescription, StatusBarIcon.Type.SystemIcon);
1300             //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
1301             mIcons.put(slot, icon);
1302 
1303             IStatusBar bar = mBar;
1304             if (bar != null) {
1305                 try {
1306                     bar.setIcon(slot, icon);
1307                 } catch (RemoteException ex) {
1308                 }
1309             }
1310         }
1311     }
1312 
1313     @Override
setIconVisibility(String slot, boolean visibility)1314     public void setIconVisibility(String slot, boolean visibility) {
1315         enforceStatusBar();
1316 
1317         synchronized (mIcons) {
1318             StatusBarIcon icon = mIcons.get(slot);
1319             if (icon == null) {
1320                 return;
1321             }
1322             if (icon.visible != visibility) {
1323                 icon.visible = visibility;
1324 
1325                 IStatusBar bar = mBar;
1326                 if (bar != null) {
1327                     try {
1328                         bar.setIcon(slot, icon);
1329                     } catch (RemoteException ex) {
1330                     }
1331                 }
1332             }
1333         }
1334     }
1335 
1336     @Override
removeIcon(String slot)1337     public void removeIcon(String slot) {
1338         enforceStatusBar();
1339 
1340         synchronized (mIcons) {
1341             mIcons.remove(slot);
1342 
1343             IStatusBar bar = mBar;
1344             if (bar != null) {
1345                 try {
1346                     bar.removeIcon(slot);
1347                 } catch (RemoteException ex) {
1348                 }
1349             }
1350         }
1351     }
1352 
1353     @Override
setImeWindowStatus(int displayId, final IBinder token, final int vis, final int backDisposition, final boolean showImeSwitcher)1354     public void setImeWindowStatus(int displayId, final IBinder token, final int vis,
1355             final int backDisposition, final boolean showImeSwitcher) {
1356         enforceStatusBar();
1357 
1358         if (SPEW) {
1359             Slog.d(TAG, "swetImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition);
1360         }
1361 
1362         synchronized(mLock) {
1363             // In case of IME change, we need to call up setImeWindowStatus() regardless of
1364             // mImeWindowVis because mImeWindowVis may not have been set to false when the
1365             // previous IME was destroyed.
1366             getUiState(displayId).setImeWindowState(vis, backDisposition, showImeSwitcher, token);
1367 
1368             mHandler.post(() -> {
1369                 if (mBar == null) return;
1370                 try {
1371                     mBar.setImeWindowStatus(
1372                             displayId, token, vis, backDisposition, showImeSwitcher);
1373                 } catch (RemoteException ex) { }
1374             });
1375         }
1376     }
1377 
setDisableFlags(int displayId, int flags, String cause)1378     private void setDisableFlags(int displayId, int flags, String cause) {
1379         // also allows calls from window manager which is in this process.
1380         enforceStatusBarService();
1381 
1382         final int unknownFlags = flags & ~StatusBarManager.DISABLE_MASK;
1383         if (unknownFlags != 0) {
1384             Slog.e(TAG, "Unknown disable flags: 0x" + Integer.toHexString(unknownFlags),
1385                     new RuntimeException());
1386         }
1387 
1388         if (SPEW) Slog.d(TAG, "setDisableFlags(0x" + Integer.toHexString(flags) + ")");
1389 
1390         synchronized (mLock) {
1391             disableLocked(displayId, mCurrentUserId, flags, mSysUiVisToken, cause, 1);
1392         }
1393     }
1394 
1395     /**
1396      * @return {@link UiState} specified by {@code displayId}.
1397      *
1398      * <p>
1399      *   Note: If {@link UiState} specified by {@code displayId} does not exist, {@link UiState}
1400      *   will be allocated and {@code mDisplayUiState} will be updated accordingly.
1401      * <p/>
1402      */
getUiState(int displayId)1403     private UiState getUiState(int displayId) {
1404         UiState state = mDisplayUiState.get(displayId);
1405         if (state == null) {
1406             state = new UiState();
1407             mDisplayUiState.put(displayId, state);
1408         }
1409         return state;
1410     }
1411 
1412     private static class UiState {
1413         private @Appearance int mAppearance = 0;
1414         private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
1415         private @InsetsType int mTransientBarTypes;
1416         private boolean mNavbarColorManagedByIme = false;
1417         private @Behavior int mBehavior;
1418         private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
1419         private String mPackageName = "none";
1420         private int mDisabled1 = 0;
1421         private int mDisabled2 = 0;
1422         private int mImeWindowVis = 0;
1423         private int mImeBackDisposition = 0;
1424         private boolean mShowImeSwitcher = false;
1425         private IBinder mImeToken = null;
1426         private LetterboxDetails[] mLetterboxDetails = new LetterboxDetails[0];
1427 
setBarAttributes(@ppearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, LetterboxDetails[] letterboxDetails)1428         private void setBarAttributes(@Appearance int appearance,
1429                 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme,
1430                 @Behavior int behavior, @InsetsType int requestedVisibleTypes,
1431                 String packageName,
1432                 LetterboxDetails[] letterboxDetails) {
1433             mAppearance = appearance;
1434             mAppearanceRegions = appearanceRegions;
1435             mNavbarColorManagedByIme = navbarColorManagedByIme;
1436             mBehavior = behavior;
1437             mRequestedVisibleTypes = requestedVisibleTypes;
1438             mPackageName = packageName;
1439             mLetterboxDetails = letterboxDetails;
1440         }
1441 
showTransient(@nsetsType int types)1442         private void showTransient(@InsetsType int types) {
1443             mTransientBarTypes |= types;
1444         }
1445 
clearTransient(@nsetsType int types)1446         private void clearTransient(@InsetsType int types) {
1447             mTransientBarTypes &= ~types;
1448         }
1449 
getDisabled1()1450         private int getDisabled1() {
1451             return mDisabled1;
1452         }
1453 
getDisabled2()1454         private int getDisabled2() {
1455             return mDisabled2;
1456         }
1457 
setDisabled(int disabled1, int disabled2)1458         private void setDisabled(int disabled1, int disabled2) {
1459             mDisabled1 = disabled1;
1460             mDisabled2 = disabled2;
1461         }
1462 
disableEquals(int disabled1, int disabled2)1463         private boolean disableEquals(int disabled1, int disabled2) {
1464             return mDisabled1 == disabled1 && mDisabled2 == disabled2;
1465         }
1466 
setImeWindowState(final int vis, final int backDisposition, final boolean showImeSwitcher, final IBinder token)1467         private void setImeWindowState(final int vis, final int backDisposition,
1468                 final boolean showImeSwitcher, final IBinder token) {
1469             mImeWindowVis = vis;
1470             mImeBackDisposition = backDisposition;
1471             mShowImeSwitcher = showImeSwitcher;
1472             mImeToken = token;
1473         }
1474     }
1475 
enforceStatusBarOrShell()1476     private void enforceStatusBarOrShell() {
1477         if (Binder.getCallingUid() == Process.SHELL_UID) {
1478             return;
1479         }
1480         enforceStatusBar();
1481     }
1482 
enforceStatusBar()1483     private void enforceStatusBar() {
1484         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
1485                 "StatusBarManagerService");
1486     }
1487 
enforceExpandStatusBar()1488     private void enforceExpandStatusBar() {
1489         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.EXPAND_STATUS_BAR,
1490                 "StatusBarManagerService");
1491     }
1492 
enforceStatusBarService()1493     private void enforceStatusBarService() {
1494         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
1495                 "StatusBarManagerService");
1496     }
1497 
enforceBiometricDialog()1498     private void enforceBiometricDialog() {
1499         mContext.enforceCallingOrSelfPermission(
1500                 android.Manifest.permission.MANAGE_BIOMETRIC_DIALOG,
1501                 "StatusBarManagerService");
1502     }
1503 
enforceMediaContentControl()1504     private void enforceMediaContentControl() {
1505         mContext.enforceCallingOrSelfPermission(
1506                 android.Manifest.permission.MEDIA_CONTENT_CONTROL,
1507                 "StatusBarManagerService");
1508     }
1509 
1510     @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
enforceControlDeviceStatePermission()1511     private void enforceControlDeviceStatePermission() {
1512         mContext.enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "StatusBarManagerService");
1513     }
1514 
doesCallerHoldInteractAcrossUserPermission()1515     private boolean doesCallerHoldInteractAcrossUserPermission() {
1516         return mContext.checkCallingPermission(INTERACT_ACROSS_USERS_FULL) == PERMISSION_GRANTED
1517                 || mContext.checkCallingPermission(INTERACT_ACROSS_USERS) == PERMISSION_GRANTED;
1518     }
1519 
1520     /**
1521      *  For targetSdk S+ we require STATUS_BAR. For targetSdk < S, we only require EXPAND_STATUS_BAR
1522      *  but also require that it falls into one of the allowed use-cases to lock down abuse vector.
1523      */
checkCanCollapseStatusBar(String method)1524     private boolean checkCanCollapseStatusBar(String method) {
1525         int uid = Binder.getCallingUid();
1526         int pid = Binder.getCallingPid();
1527         if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) {
1528             enforceStatusBar();
1529         } else {
1530             if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid)
1531                     != PERMISSION_GRANTED) {
1532                 enforceExpandStatusBar();
1533                 if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) {
1534                     Slog.e(TAG, "Permission Denial: Method " + method + "() requires permission "
1535                             + Manifest.permission.STATUS_BAR + ", ignoring call.");
1536                     return false;
1537                 }
1538             }
1539         }
1540         return true;
1541     }
1542 
1543     // ================================================================================
1544     // Callbacks from the status bar service.
1545     // ================================================================================
1546     // TODO(b/118592525): refactor it as an IStatusBar API.
1547     @Override
registerStatusBar(IStatusBar bar)1548     public RegisterStatusBarResult registerStatusBar(IStatusBar bar) {
1549         enforceStatusBarService();
1550 
1551         Slog.i(TAG, "registerStatusBar bar=" + bar);
1552         mBar = bar;
1553         mDeathRecipient.linkToDeath();
1554         notifyBarAttachChanged();
1555         final ArrayMap<String, StatusBarIcon> icons;
1556         synchronized (mIcons) {
1557             icons = new ArrayMap<>(mIcons);
1558         }
1559         synchronized (mLock) {
1560             // TODO(b/118592525): Currently, status bar only works on the default display.
1561             // Make it aware of multi-display if needed.
1562             final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
1563             return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
1564                     state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
1565                     state.mImeBackDisposition, state.mShowImeSwitcher,
1566                     gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
1567                     state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes,
1568                     state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails);
1569         }
1570     }
1571 
notifyBarAttachChanged()1572     private void notifyBarAttachChanged() {
1573         UiThread.getHandler().post(() -> {
1574             if (mGlobalActionListener == null) return;
1575             mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);
1576         });
1577         // If StatusBarService dies, system_server doesn't get killed with it, so we need to make
1578         // sure the UDFPS callback is refreshed as well. Deferring to the handler just so to avoid
1579         // making registerStatusBar re-entrant.
1580         mHandler.post(() -> {
1581             synchronized (mLock) {
1582                 setUdfpsRefreshRateCallback(mUdfpsRefreshRateRequestCallback);
1583                 setBiometicContextListener(mBiometricContextListener);
1584             }
1585         });
1586     }
1587 
1588     @VisibleForTesting
registerOverlayManager(IOverlayManager overlayManager)1589     void registerOverlayManager(IOverlayManager overlayManager) {
1590         mOverlayManager = overlayManager;
1591     }
1592 
1593     /**
1594      * @param clearNotificationEffects whether to consider notifications as "shown" and stop
1595      *     LED, vibration, and ringing
1596      */
1597     @Override
onPanelRevealed(boolean clearNotificationEffects, int numItems)1598     public void onPanelRevealed(boolean clearNotificationEffects, int numItems) {
1599         enforceStatusBarService();
1600         final long identity = Binder.clearCallingIdentity();
1601         try {
1602             mNotificationDelegate.onPanelRevealed(clearNotificationEffects, numItems);
1603         } finally {
1604             Binder.restoreCallingIdentity(identity);
1605         }
1606     }
1607 
1608     @Override
clearNotificationEffects()1609     public void clearNotificationEffects() throws RemoteException {
1610         enforceStatusBarService();
1611         final long identity = Binder.clearCallingIdentity();
1612         try {
1613             mNotificationDelegate.clearEffects();
1614         } finally {
1615             Binder.restoreCallingIdentity(identity);
1616         }
1617     }
1618 
1619     @Override
onPanelHidden()1620     public void onPanelHidden() throws RemoteException {
1621         enforceStatusBarService();
1622         final long identity = Binder.clearCallingIdentity();
1623         try {
1624             mNotificationDelegate.onPanelHidden();
1625         } finally {
1626             Binder.restoreCallingIdentity(identity);
1627         }
1628     }
1629 
1630     /**
1631      * Allows the status bar to shutdown the device.
1632      */
1633     @Override
shutdown()1634     public void shutdown() {
1635         enforceStatusBarService();
1636         String reason = PowerManager.SHUTDOWN_USER_REQUESTED;
1637         ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
1638         final long identity = Binder.clearCallingIdentity();
1639         try {
1640             mNotificationDelegate.prepareForPossibleShutdown();
1641             // ShutdownThread displays UI, so give it a UI context.
1642             mHandler.post(() ->
1643                     ShutdownThread.shutdown(getUiContext(), reason, false));
1644         } finally {
1645             Binder.restoreCallingIdentity(identity);
1646         }
1647     }
1648 
1649     /**
1650      * Allows the status bar to reboot the device.
1651      */
1652     @Override
reboot(boolean safeMode)1653     public void reboot(boolean safeMode) {
1654         enforceStatusBarService();
1655         String reason = safeMode
1656                 ? PowerManager.REBOOT_SAFE_MODE
1657                 : PowerManager.SHUTDOWN_USER_REQUESTED;
1658         ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
1659         final long identity = Binder.clearCallingIdentity();
1660         try {
1661             mNotificationDelegate.prepareForPossibleShutdown();
1662             mHandler.post(() -> {
1663                 // ShutdownThread displays UI, so give it a UI context.
1664                 if (safeMode) {
1665                     ShutdownThread.rebootSafeMode(getUiContext(), true);
1666                 } else {
1667                     ShutdownThread.reboot(getUiContext(), reason, false);
1668                 }
1669             });
1670         } finally {
1671             Binder.restoreCallingIdentity(identity);
1672         }
1673     }
1674 
1675     /**
1676      * Allows the status bar to restart android (vs a full reboot).
1677      */
1678     @Override
restart()1679     public void restart() {
1680         enforceStatusBarService();
1681         final long identity = Binder.clearCallingIdentity();
1682         try {
1683             mHandler.post(() -> {
1684                 mActivityManagerInternal.restart();
1685             });
1686         } finally {
1687             Binder.restoreCallingIdentity(identity);
1688         }
1689     }
1690 
1691     @Override
onGlobalActionsShown()1692     public void onGlobalActionsShown() {
1693         enforceStatusBarService();
1694         final long identity = Binder.clearCallingIdentity();
1695         try {
1696             if (mGlobalActionListener == null) return;
1697             mGlobalActionListener.onGlobalActionsShown();
1698         } finally {
1699             Binder.restoreCallingIdentity(identity);
1700         }
1701     }
1702 
1703     @Override
onGlobalActionsHidden()1704     public void onGlobalActionsHidden() {
1705         enforceStatusBarService();
1706         final long identity = Binder.clearCallingIdentity();
1707         try {
1708             if (mGlobalActionListener == null) return;
1709             mGlobalActionListener.onGlobalActionsDismissed();
1710         } finally {
1711             Binder.restoreCallingIdentity(identity);
1712         }
1713     }
1714 
1715     @Override
onNotificationClick(String key, NotificationVisibility nv)1716     public void onNotificationClick(String key, NotificationVisibility nv) {
1717         enforceStatusBarService();
1718         final int callingUid = Binder.getCallingUid();
1719         final int callingPid = Binder.getCallingPid();
1720         final long identity = Binder.clearCallingIdentity();
1721         try {
1722             mNotificationDelegate.onNotificationClick(callingUid, callingPid, key, nv);
1723         } finally {
1724             Binder.restoreCallingIdentity(identity);
1725         }
1726     }
1727 
1728     @Override
onNotificationActionClick( String key, int actionIndex, Notification.Action action, NotificationVisibility nv, boolean generatedByAssistant)1729     public void onNotificationActionClick(
1730             String key, int actionIndex, Notification.Action action, NotificationVisibility nv,
1731             boolean generatedByAssistant) {
1732         enforceStatusBarService();
1733         final int callingUid = Binder.getCallingUid();
1734         final int callingPid = Binder.getCallingPid();
1735         final long identity = Binder.clearCallingIdentity();
1736         try {
1737             mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key,
1738                     actionIndex, action, nv, generatedByAssistant);
1739         } finally {
1740             Binder.restoreCallingIdentity(identity);
1741         }
1742     }
1743 
1744     @Override
onNotificationError(String pkg, String tag, int id, int uid, int initialPid, String message, int userId)1745     public void onNotificationError(String pkg, String tag, int id,
1746             int uid, int initialPid, String message, int userId) {
1747         enforceStatusBarService();
1748         final int callingUid = Binder.getCallingUid();
1749         final int callingPid = Binder.getCallingPid();
1750         final long identity = Binder.clearCallingIdentity();
1751         try {
1752             // WARNING: this will call back into us to do the remove.  Don't hold any locks.
1753             mNotificationDelegate.onNotificationError(callingUid, callingPid,
1754                     pkg, tag, id, uid, initialPid, message, userId);
1755         } finally {
1756             Binder.restoreCallingIdentity(identity);
1757         }
1758     }
1759 
1760     @Override
onNotificationClear(String pkg, int userId, String key, @NotificationStats.DismissalSurface int dismissalSurface, @NotificationStats.DismissalSentiment int dismissalSentiment, NotificationVisibility nv)1761     public void onNotificationClear(String pkg, int userId, String key,
1762             @NotificationStats.DismissalSurface int dismissalSurface,
1763             @NotificationStats.DismissalSentiment int dismissalSentiment,
1764             NotificationVisibility nv) {
1765         enforceStatusBarService();
1766         final int callingUid = Binder.getCallingUid();
1767         final int callingPid = Binder.getCallingPid();
1768         final long identity = Binder.clearCallingIdentity();
1769         try {
1770             mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, userId,
1771                     key, dismissalSurface, dismissalSentiment, nv);
1772         } finally {
1773             Binder.restoreCallingIdentity(identity);
1774         }
1775     }
1776 
1777     @Override
onNotificationVisibilityChanged( NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys)1778     public void onNotificationVisibilityChanged(
1779             NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys)
1780             throws RemoteException {
1781         enforceStatusBarService();
1782         final long identity = Binder.clearCallingIdentity();
1783         try {
1784             mNotificationDelegate.onNotificationVisibilityChanged(
1785                     newlyVisibleKeys, noLongerVisibleKeys);
1786         } finally {
1787             Binder.restoreCallingIdentity(identity);
1788         }
1789     }
1790 
1791     @Override
onNotificationExpansionChanged(String key, boolean userAction, boolean expanded, int location)1792     public void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded,
1793             int location) throws RemoteException {
1794         enforceStatusBarService();
1795         final long identity = Binder.clearCallingIdentity();
1796         try {
1797             mNotificationDelegate.onNotificationExpansionChanged(
1798                     key, userAction, expanded, location);
1799         } finally {
1800             Binder.restoreCallingIdentity(identity);
1801         }
1802     }
1803 
1804     @Override
onNotificationDirectReplied(String key)1805     public void onNotificationDirectReplied(String key) throws RemoteException {
1806         enforceStatusBarService();
1807         final long identity = Binder.clearCallingIdentity();
1808         try {
1809             mNotificationDelegate.onNotificationDirectReplied(key);
1810         } finally {
1811             Binder.restoreCallingIdentity(identity);
1812         }
1813     }
1814 
1815     @Override
onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount, boolean generatedByAssistant, boolean editBeforeSending)1816     public void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount,
1817             int smartActionCount, boolean generatedByAssistant, boolean editBeforeSending) {
1818         enforceStatusBarService();
1819         final long identity = Binder.clearCallingIdentity();
1820         try {
1821             mNotificationDelegate.onNotificationSmartSuggestionsAdded(key, smartReplyCount,
1822                     smartActionCount, generatedByAssistant, editBeforeSending);
1823         } finally {
1824             Binder.restoreCallingIdentity(identity);
1825         }
1826     }
1827 
1828     @Override
onNotificationSmartReplySent( String key, int replyIndex, CharSequence reply, int notificationLocation, boolean modifiedBeforeSending)1829     public void onNotificationSmartReplySent(
1830             String key, int replyIndex, CharSequence reply, int notificationLocation,
1831             boolean modifiedBeforeSending) throws RemoteException {
1832         enforceStatusBarService();
1833         final long identity = Binder.clearCallingIdentity();
1834         try {
1835             mNotificationDelegate.onNotificationSmartReplySent(key, replyIndex, reply,
1836                     notificationLocation, modifiedBeforeSending);
1837         } finally {
1838             Binder.restoreCallingIdentity(identity);
1839         }
1840     }
1841 
1842     @Override
onNotificationSettingsViewed(String key)1843     public void onNotificationSettingsViewed(String key) throws RemoteException {
1844         enforceStatusBarService();
1845         final long identity = Binder.clearCallingIdentity();
1846         try {
1847             mNotificationDelegate.onNotificationSettingsViewed(key);
1848         } finally {
1849             Binder.restoreCallingIdentity(identity);
1850         }
1851     }
1852 
1853     @Override
onClearAllNotifications(int userId)1854     public void onClearAllNotifications(int userId) {
1855         enforceStatusBarService();
1856         final int callingUid = Binder.getCallingUid();
1857         final int callingPid = Binder.getCallingPid();
1858         final long identity = Binder.clearCallingIdentity();
1859         try {
1860             mNotificationDelegate.onClearAll(callingUid, callingPid, userId);
1861         } finally {
1862             Binder.restoreCallingIdentity(identity);
1863         }
1864     }
1865 
1866     @Override
onNotificationBubbleChanged(String key, boolean isBubble, int flags)1867     public void onNotificationBubbleChanged(String key, boolean isBubble, int flags) {
1868         enforceStatusBarService();
1869         final long identity = Binder.clearCallingIdentity();
1870         try {
1871             mNotificationDelegate.onNotificationBubbleChanged(key, isBubble, flags);
1872         } finally {
1873             Binder.restoreCallingIdentity(identity);
1874         }
1875     }
1876 
1877     @Override
onBubbleMetadataFlagChanged(String key, int flags)1878     public void onBubbleMetadataFlagChanged(String key, int flags) {
1879         enforceStatusBarService();
1880         final long identity = Binder.clearCallingIdentity();
1881         try {
1882             mNotificationDelegate.onBubbleMetadataFlagChanged(key, flags);
1883         } finally {
1884             Binder.restoreCallingIdentity(identity);
1885         }
1886     }
1887 
1888     @Override
hideCurrentInputMethodForBubbles(int displayId)1889     public void hideCurrentInputMethodForBubbles(int displayId) {
1890         enforceStatusBarService();
1891         final long token = Binder.clearCallingIdentity();
1892         try {
1893             // TODO(b/308479256): Check if hiding "all" IMEs is OK or not.
1894             InputMethodManagerInternal.get().hideAllInputMethods(
1895                     SoftInputShowHideReason.HIDE_BUBBLES, displayId);
1896         } finally {
1897             Binder.restoreCallingIdentity(token);
1898         }
1899     }
1900 
1901     @Override
grantInlineReplyUriPermission(String key, Uri uri, UserHandle user, String packageName)1902     public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user,
1903             String packageName) {
1904         enforceStatusBarService();
1905         int callingUid = Binder.getCallingUid();
1906         final long identity = Binder.clearCallingIdentity();
1907         try {
1908             mNotificationDelegate.grantInlineReplyUriPermission(key, uri, user, packageName,
1909                     callingUid);
1910         } finally {
1911             Binder.restoreCallingIdentity(identity);
1912         }
1913     }
1914 
1915     @Override
clearInlineReplyUriPermissions(String key)1916     public void clearInlineReplyUriPermissions(String key) {
1917         enforceStatusBarService();
1918         int callingUid = Binder.getCallingUid();
1919         final long identity = Binder.clearCallingIdentity();
1920         try {
1921             mNotificationDelegate.clearInlineReplyUriPermissions(key, callingUid);
1922         } finally {
1923             Binder.restoreCallingIdentity(identity);
1924         }
1925     }
1926 
1927     @Override
onNotificationFeedbackReceived(String key, Bundle feedback)1928     public void onNotificationFeedbackReceived(String key, Bundle feedback) {
1929         enforceStatusBarService();
1930         final long identity = Binder.clearCallingIdentity();
1931         try {
1932             mNotificationDelegate.onNotificationFeedbackReceived(key, feedback);
1933         } finally {
1934             Binder.restoreCallingIdentity(identity);
1935         }
1936     }
1937 
1938 
1939     @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1940     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1941             String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
1942         (new StatusBarShellCommand(this, mContext)).exec(
1943                 this, in, out, err, args, callback, resultReceiver);
1944     }
1945 
1946     @Override
showInattentiveSleepWarning()1947     public void showInattentiveSleepWarning() {
1948         enforceStatusBarService();
1949         IStatusBar bar = mBar;
1950         if (bar != null) {
1951             try {
1952                 bar.showInattentiveSleepWarning();
1953             } catch (RemoteException ex) {
1954             }
1955         }
1956     }
1957 
1958     @Override
dismissInattentiveSleepWarning(boolean animated)1959     public void dismissInattentiveSleepWarning(boolean animated) {
1960         enforceStatusBarService();
1961         IStatusBar bar = mBar;
1962         if (bar != null) {
1963             try {
1964                 bar.dismissInattentiveSleepWarning(animated);
1965             } catch (RemoteException ex) {
1966             }
1967         }
1968     }
1969 
1970     @Override
suppressAmbientDisplay(boolean suppress)1971     public void suppressAmbientDisplay(boolean suppress) {
1972         enforceStatusBarService();
1973         IStatusBar bar = mBar;
1974         if (bar != null) {
1975             try {
1976                 bar.suppressAmbientDisplay(suppress);
1977             } catch (RemoteException ex) {
1978             }
1979         }
1980     }
1981 
checkCallingUidPackage(String packageName, int callingUid, int userId)1982     private void checkCallingUidPackage(String packageName, int callingUid, int userId) {
1983         int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
1984         if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(packageUid)) {
1985             throw new SecurityException("Package " + packageName
1986                     + " does not belong to the calling uid " + callingUid);
1987         }
1988     }
1989 
isComponentValidTileService(ComponentName componentName, int userId)1990     private ResolveInfo isComponentValidTileService(ComponentName componentName, int userId) {
1991         Intent intent = new Intent(TileService.ACTION_QS_TILE);
1992         intent.setComponent(componentName);
1993         ResolveInfo r = mPackageManagerInternal.resolveService(intent,
1994                 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 0, userId,
1995                 Process.myUid());
1996         int enabled = mPackageManagerInternal.getComponentEnabledSetting(
1997                 componentName, Process.myUid(), userId);
1998         if (r != null
1999                 && r.serviceInfo != null
2000                 && resolveEnabledComponent(r.serviceInfo.enabled, enabled)
2001                 && Manifest.permission.BIND_QUICK_SETTINGS_TILE.equals(r.serviceInfo.permission)) {
2002             return r;
2003         } else {
2004             return null;
2005         }
2006     }
2007 
resolveEnabledComponent(boolean defaultValue, int pmResult)2008     private boolean resolveEnabledComponent(boolean defaultValue, int pmResult) {
2009         if (pmResult == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
2010             return true;
2011         }
2012         if (pmResult == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
2013             return defaultValue;
2014         }
2015         return false;
2016     }
2017 
2018     @Override
requestTileServiceListeningState( @onNull ComponentName componentName, int userId )2019     public void requestTileServiceListeningState(
2020             @NonNull ComponentName componentName,
2021             int userId
2022     ) {
2023         int callingUid = Binder.getCallingUid();
2024         String packageName = componentName.getPackageName();
2025 
2026         boolean mustPerformChecks = CompatChanges.isChangeEnabled(
2027                 REQUEST_LISTENING_MUST_MATCH_PACKAGE, callingUid);
2028 
2029         if (mustPerformChecks) {
2030             // Check calling user can act on behalf of current user
2031             userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid,
2032                     userId, false, ActivityManagerInternal.ALLOW_NON_FULL,
2033                     "requestTileServiceListeningState", packageName);
2034 
2035             // Check calling uid matches package
2036             checkCallingUidPackage(packageName, callingUid, userId);
2037 
2038             int currentUser = mActivityManagerInternal.getCurrentUserId();
2039 
2040             // Check current user
2041             if (userId != currentUser) {
2042                 if (CompatChanges.isChangeEnabled(REQUEST_LISTENING_OTHER_USER_NOOP, callingUid)) {
2043                     return;
2044                 } else {
2045                     throw new IllegalArgumentException(
2046                             "User " + userId + " is not the current user.");
2047                 }
2048             }
2049         }
2050         IStatusBar bar = mBar;
2051         if (bar != null) {
2052             try {
2053                 bar.requestTileServiceListeningState(componentName);
2054             } catch (RemoteException e) {
2055                 Slog.e(TAG, "requestTileServiceListeningState", e);
2056             }
2057         }
2058     }
2059 
2060     @Override
requestAddTile( @onNull ComponentName componentName, @NonNull CharSequence label, @NonNull Icon icon, int userId, @NonNull IAddTileResultCallback callback )2061     public void requestAddTile(
2062             @NonNull ComponentName componentName,
2063             @NonNull CharSequence label,
2064             @NonNull Icon icon,
2065             int userId,
2066             @NonNull IAddTileResultCallback callback
2067     ) {
2068         int callingUid = Binder.getCallingUid();
2069         String packageName = componentName.getPackageName();
2070 
2071         // Check calling user can act on behalf of current user
2072         mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
2073                 false, ActivityManagerInternal.ALLOW_NON_FULL, "requestAddTile", packageName);
2074 
2075         // Check calling uid matches package
2076         checkCallingUidPackage(packageName, callingUid, userId);
2077 
2078         int currentUser = mActivityManagerInternal.getCurrentUserId();
2079 
2080         // Check current user
2081         if (userId != currentUser) {
2082             try {
2083                 callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_NOT_CURRENT_USER);
2084             } catch (RemoteException e) {
2085                 Slog.e(TAG, "requestAddTile", e);
2086             }
2087             return;
2088         }
2089 
2090         // We've checked that the package, component name and uid all match.
2091         ResolveInfo r = isComponentValidTileService(componentName, userId);
2092         if (r == null || !r.serviceInfo.exported) {
2093             try {
2094                 callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_BAD_COMPONENT);
2095             } catch (RemoteException e) {
2096                 Slog.e(TAG, "requestAddTile", e);
2097             }
2098             return;
2099         }
2100 
2101         final int procState = mActivityManagerInternal.getUidProcessState(callingUid);
2102         if (ActivityManager.RunningAppProcessInfo.procStateToImportance(procState)
2103                 != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
2104             try {
2105                 callback.onTileRequest(
2106                         StatusBarManager.TILE_ADD_REQUEST_ERROR_APP_NOT_IN_FOREGROUND);
2107             } catch (RemoteException e) {
2108                 Slog.e(TAG, "requestAddTile", e);
2109             }
2110             return;
2111         }
2112 
2113         synchronized (mCurrentRequestAddTilePackages) {
2114             Long lastTime = mCurrentRequestAddTilePackages.get(packageName);
2115             final long currentTime = System.nanoTime();
2116             if (lastTime != null && currentTime - lastTime < REQUEST_TIME_OUT) {
2117                 try {
2118                     callback.onTileRequest(
2119                             StatusBarManager.TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS);
2120                 } catch (RemoteException e) {
2121                     Slog.e(TAG, "requestAddTile", e);
2122                 }
2123                 return;
2124             } else {
2125                 if (lastTime != null) {
2126                     cancelRequestAddTileInternal(packageName);
2127                 }
2128             }
2129 
2130             mCurrentRequestAddTilePackages.put(packageName, currentTime);
2131         }
2132 
2133         if (mTileRequestTracker.shouldBeDenied(userId, componentName)) {
2134             if (clearTileAddRequest(packageName)) {
2135                 try {
2136                     callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED);
2137                 } catch (RemoteException e) {
2138                     Slog.e(TAG, "requestAddTile - callback", e);
2139                 }
2140             }
2141             return;
2142         }
2143 
2144         IAddTileResultCallback proxyCallback = new IAddTileResultCallback.Stub() {
2145             @Override
2146             public void onTileRequest(int i) {
2147                 if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED) {
2148                     i = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED;
2149                 } else if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED) {
2150                     mTileRequestTracker.addDenial(userId, componentName);
2151                 } else if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ADDED) {
2152                     mTileRequestTracker.resetRequests(userId, componentName);
2153                 }
2154                 if (clearTileAddRequest(packageName)) {
2155                     try {
2156                         callback.onTileRequest(i);
2157                     } catch (RemoteException e) {
2158                         Slog.e(TAG, "requestAddTile - callback", e);
2159                     }
2160                 }
2161             }
2162         };
2163 
2164         CharSequence appName = r.serviceInfo.applicationInfo
2165                 .loadLabel(mContext.getPackageManager());
2166         IStatusBar bar = mBar;
2167         if (bar != null) {
2168             try {
2169                 bar.requestAddTile(callingUid, componentName, appName, label, icon, proxyCallback);
2170                 return;
2171             } catch (RemoteException e) {
2172                 Slog.e(TAG, "requestAddTile", e);
2173             }
2174         }
2175         clearTileAddRequest(packageName);
2176         try {
2177             callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE);
2178         } catch (RemoteException e) {
2179             Slog.e(TAG, "requestAddTile", e);
2180         }
2181     }
2182 
2183     @Override
cancelRequestAddTile(@onNull String packageName)2184     public void cancelRequestAddTile(@NonNull String packageName) {
2185         enforceStatusBar();
2186         cancelRequestAddTileInternal(packageName);
2187     }
2188 
cancelRequestAddTileInternal(String packageName)2189     private void cancelRequestAddTileInternal(String packageName) {
2190         clearTileAddRequest(packageName);
2191         IStatusBar bar = mBar;
2192         if (bar != null) {
2193             try {
2194                 bar.cancelRequestAddTile(packageName);
2195             } catch (RemoteException e) {
2196                 Slog.e(TAG, "requestAddTile", e);
2197             }
2198         }
2199     }
2200 
clearTileAddRequest(String packageName)2201     private boolean clearTileAddRequest(String packageName) {
2202         synchronized (mCurrentRequestAddTilePackages) {
2203             return mCurrentRequestAddTilePackages.remove(packageName) != null;
2204         }
2205     }
2206 
2207     @Override
onSessionStarted(@essionFlags int sessionType, InstanceId instance)2208     public void onSessionStarted(@SessionFlags int sessionType, InstanceId instance) {
2209         mSessionMonitor.onSessionStarted(sessionType, instance);
2210     }
2211 
2212     @Override
onSessionEnded(@essionFlags int sessionType, InstanceId instance)2213     public void onSessionEnded(@SessionFlags int sessionType, InstanceId instance) {
2214         mSessionMonitor.onSessionEnded(sessionType, instance);
2215     }
2216 
2217     @Override
registerSessionListener(@essionFlags int sessionFlags, ISessionListener listener)2218     public void registerSessionListener(@SessionFlags int sessionFlags,
2219             ISessionListener listener) {
2220         mSessionMonitor.registerSessionListener(sessionFlags, listener);
2221     }
2222 
2223     @Override
unregisterSessionListener(@essionFlags int sessionFlags, ISessionListener listener)2224     public void unregisterSessionListener(@SessionFlags int sessionFlags,
2225             ISessionListener listener) {
2226         mSessionMonitor.unregisterSessionListener(sessionFlags, listener);
2227     }
2228 
getStatusBarIcons()2229     public String[] getStatusBarIcons() {
2230         return mContext.getResources().getStringArray(R.array.config_statusBarIcons);
2231     }
2232 
2233     /**
2234      * Sets or removes the navigation bar mode.
2235      *
2236      * @param navBarMode the mode of the navigation bar to be set.
2237      */
setNavBarMode(@avBarMode int navBarMode)2238     public void setNavBarMode(@NavBarMode int navBarMode) {
2239         enforceStatusBar();
2240         if (navBarMode != NAV_BAR_MODE_DEFAULT && navBarMode != NAV_BAR_MODE_KIDS) {
2241             throw new IllegalArgumentException("Supplied navBarMode not supported: " + navBarMode);
2242         }
2243 
2244         final int userId = mCurrentUserId;
2245         final int callingUserId = UserHandle.getUserId(Binder.getCallingUid());
2246         if (mCurrentUserId != callingUserId && !doesCallerHoldInteractAcrossUserPermission()) {
2247             throw new SecurityException("Calling user id: " + callingUserId
2248                     + ", cannot call on behalf of current user id: " + mCurrentUserId + ".");
2249         }
2250         final long userIdentity = Binder.clearCallingIdentity();
2251         try {
2252             Settings.Secure.putIntForUser(mContext.getContentResolver(),
2253                     Settings.Secure.NAV_BAR_KIDS_MODE, navBarMode, userId);
2254             Settings.Secure.putIntForUser(mContext.getContentResolver(),
2255                     Settings.Secure.NAV_BAR_FORCE_VISIBLE, navBarMode, userId);
2256 
2257             IOverlayManager overlayManager = getOverlayManager();
2258             if (overlayManager != null && navBarMode == NAV_BAR_MODE_KIDS
2259                     && isPackageSupported(NAV_BAR_MODE_3BUTTON_OVERLAY)) {
2260                 overlayManager.setEnabledExclusiveInCategory(NAV_BAR_MODE_3BUTTON_OVERLAY, userId);
2261             }
2262         } catch (RemoteException e) {
2263             throw e.rethrowFromSystemServer();
2264         } finally {
2265             Binder.restoreCallingIdentity(userIdentity);
2266         }
2267     }
2268 
2269     /**
2270      * Gets the navigation bar mode. Returns default value if no mode is set.
2271      *
2272      * @hide
2273      */
getNavBarMode()2274     public @NavBarMode int getNavBarMode() {
2275         enforceStatusBar();
2276 
2277         int navBarKidsMode = NAV_BAR_MODE_DEFAULT;
2278         final int userId = mCurrentUserId;
2279         final long userIdentity = Binder.clearCallingIdentity();
2280         try {
2281             navBarKidsMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
2282                     Settings.Secure.NAV_BAR_KIDS_MODE, userId);
2283         } catch (Settings.SettingNotFoundException ex) {
2284             return navBarKidsMode;
2285         } finally {
2286             Binder.restoreCallingIdentity(userIdentity);
2287         }
2288         return navBarKidsMode;
2289     }
2290 
isPackageSupported(String packageName)2291     private boolean isPackageSupported(String packageName) {
2292         if (packageName == null) {
2293             return false;
2294         }
2295         try {
2296             return mContext.getPackageManager().getPackageInfo(packageName,
2297                     PackageManager.PackageInfoFlags.of(0)) != null;
2298         } catch (PackageManager.NameNotFoundException ignored) {
2299             if (SPEW) {
2300                 Slog.d(TAG, "Package not found: " + packageName);
2301             }
2302         }
2303         return false;
2304     }
2305 
2306     /**
2307      * Notifies the system of a new media tap-to-transfer state for the *sender* device. See
2308      * {@link StatusBarManager.updateMediaTapToTransferSenderDisplay} for more information.
2309      *
2310      * @param undoCallback a callback that will be triggered if the user elects to undo a media
2311      *                     transfer.
2312      *
2313      * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL}
2314      * permission.
2315      */
2316     @Override
updateMediaTapToTransferSenderDisplay( @tatusBarManager.MediaTransferSenderState int displayState, @NonNull MediaRoute2Info routeInfo, @Nullable IUndoMediaTransferCallback undoCallback )2317     public void updateMediaTapToTransferSenderDisplay(
2318             @StatusBarManager.MediaTransferSenderState int displayState,
2319             @NonNull MediaRoute2Info routeInfo,
2320             @Nullable IUndoMediaTransferCallback undoCallback
2321     ) {
2322         enforceMediaContentControl();
2323         IStatusBar bar = mBar;
2324         if (bar != null) {
2325             try {
2326                 bar.updateMediaTapToTransferSenderDisplay(displayState, routeInfo, undoCallback);
2327             } catch (RemoteException e) {
2328                 Slog.e(TAG, "updateMediaTapToTransferSenderDisplay", e);
2329             }
2330         }
2331     }
2332 
2333     /**
2334      * Notifies the system of a new media tap-to-transfer state for the *receiver* device. See
2335      * {@link StatusBarManager.updateMediaTapToTransferReceiverDisplay} for more information.
2336      *
2337      * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL}
2338      * permission.
2339      */
2340     @Override
updateMediaTapToTransferReceiverDisplay( @tatusBarManager.MediaTransferReceiverState int displayState, MediaRoute2Info routeInfo, @Nullable Icon appIcon, @Nullable CharSequence appName)2341     public void updateMediaTapToTransferReceiverDisplay(
2342             @StatusBarManager.MediaTransferReceiverState int displayState,
2343             MediaRoute2Info routeInfo,
2344             @Nullable Icon appIcon,
2345             @Nullable CharSequence appName) {
2346         enforceMediaContentControl();
2347         IStatusBar bar = mBar;
2348         if (bar != null) {
2349             try {
2350                 bar.updateMediaTapToTransferReceiverDisplay(
2351                         displayState, routeInfo, appIcon, appName);
2352             } catch (RemoteException e) {
2353                 Slog.e(TAG, "updateMediaTapToTransferReceiverDisplay", e);
2354             }
2355         }
2356     }
2357 
2358     /**
2359      * Registers a provider that gives information about nearby devices that are able to play media.
2360      * See {@link StatusBarmanager.registerNearbyMediaDevicesProvider}.
2361      *
2362      * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL}
2363      * permission.
2364      *
2365      * @param provider the nearby device information provider to register
2366      *
2367      * @hide
2368      */
2369     @Override
registerNearbyMediaDevicesProvider( @onNull INearbyMediaDevicesProvider provider )2370     public void registerNearbyMediaDevicesProvider(
2371             @NonNull INearbyMediaDevicesProvider provider
2372     ) {
2373         enforceMediaContentControl();
2374         IStatusBar bar = mBar;
2375         if (bar != null) {
2376             try {
2377                 bar.registerNearbyMediaDevicesProvider(provider);
2378             } catch (RemoteException e) {
2379                 Slog.e(TAG, "registerNearbyMediaDevicesProvider", e);
2380             }
2381         }
2382     }
2383 
2384     /**
2385      * Unregisters a provider that gives information about nearby devices that are able to play
2386      * media. See {@link StatusBarmanager.unregisterNearbyMediaDevicesProvider}.
2387      *
2388      * Requires the caller to have the {@link android.Manifest.permission.MEDIA_CONTENT_CONTROL}
2389      * permission.
2390      *
2391      * @param provider the nearby device information provider to unregister
2392      *
2393      * @hide
2394      */
2395     @Override
unregisterNearbyMediaDevicesProvider( @onNull INearbyMediaDevicesProvider provider )2396     public void unregisterNearbyMediaDevicesProvider(
2397             @NonNull INearbyMediaDevicesProvider provider
2398     ) {
2399         enforceMediaContentControl();
2400         IStatusBar bar = mBar;
2401         if (bar != null) {
2402             try {
2403                 bar.unregisterNearbyMediaDevicesProvider(provider);
2404             } catch (RemoteException e) {
2405                 Slog.e(TAG, "unregisterNearbyMediaDevicesProvider", e);
2406             }
2407         }
2408     }
2409 
2410     @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
2411     @Override
showRearDisplayDialog(int currentState)2412     public void showRearDisplayDialog(int currentState) {
2413         enforceControlDeviceStatePermission();
2414         IStatusBar bar = mBar;
2415         if (bar != null) {
2416             try {
2417                 bar.showRearDisplayDialog(currentState);
2418             } catch (RemoteException e) {
2419                 Slog.e(TAG, "showRearDisplayDialog", e);
2420             }
2421         }
2422     }
2423 
2424     /** @hide */
passThroughShellCommand(String[] args, FileDescriptor fd)2425     public void passThroughShellCommand(String[] args, FileDescriptor fd) {
2426         enforceStatusBarOrShell();
2427         if (mBar == null)  return;
2428 
2429         try (TransferPipe tp = new TransferPipe()) {
2430             // Sending the command to the remote, which needs to execute async to avoid blocking
2431             // See Binder#dumpAsync() for inspiration
2432             tp.setBufferPrefix("  ");
2433             mBar.passThroughShellCommand(args, tp.getWriteFd());
2434             // Times out after 5s
2435             tp.go(fd);
2436         } catch (Throwable t) {
2437             Slog.e(TAG, "Error sending command to IStatusBar", t);
2438         }
2439     }
2440 
2441     // ================================================================================
2442     // Can be called from any thread
2443     // ================================================================================
2444 
2445     // lock on mDisableRecords
manageDisableListLocked(int userId, int what, IBinder token, String pkg, int which)2446     void manageDisableListLocked(int userId, int what, IBinder token, String pkg, int which) {
2447         if (SPEW) {
2448             Slog.d(TAG, "manageDisableList userId=" + userId
2449                     + " what=0x" + Integer.toHexString(what) + " pkg=" + pkg);
2450         }
2451 
2452         // Find matching record, if any
2453         Pair<Integer, DisableRecord> match = findMatchingRecordLocked(token, userId);
2454         int i = match.first;
2455         DisableRecord record = match.second;
2456 
2457         // Remove record if binder is already dead
2458         if (!token.isBinderAlive()) {
2459             if (record != null) {
2460                 mDisableRecords.remove(i);
2461                 record.token.unlinkToDeath(record, 0);
2462             }
2463             return;
2464         }
2465 
2466         // Update existing record
2467         if (record != null) {
2468             record.setFlags(what, which, pkg);
2469             if (record.isEmpty()) {
2470                 mDisableRecords.remove(i);
2471                 record.token.unlinkToDeath(record, 0);
2472             }
2473             return;
2474         }
2475 
2476         // Record doesn't exist, so we create a new one
2477         record = new DisableRecord(userId, token);
2478         record.setFlags(what, which, pkg);
2479         mDisableRecords.add(record);
2480     }
2481 
2482     @Nullable
2483     @GuardedBy("mLock")
findMatchingRecordLocked(IBinder token, int userId)2484     private Pair<Integer, DisableRecord> findMatchingRecordLocked(IBinder token, int userId) {
2485         final int numRecords = mDisableRecords.size();
2486         DisableRecord record = null;
2487         int i;
2488         for (i = 0; i < numRecords; i++) {
2489             DisableRecord r = mDisableRecords.get(i);
2490             if (r.token == token && r.userId == userId) {
2491                 record = r;
2492                 break;
2493             }
2494         }
2495 
2496         return new Pair<Integer, DisableRecord>(i, record);
2497     }
2498 
2499     // lock on mDisableRecords
gatherDisableActionsLocked(int userId, int which)2500     int gatherDisableActionsLocked(int userId, int which) {
2501         final int N = mDisableRecords.size();
2502         // gather the new net flags
2503         int net = 0;
2504         for (int i=0; i<N; i++) {
2505             final DisableRecord rec = mDisableRecords.get(i);
2506             if (rec.userId == userId) {
2507                 net |= rec.getFlags(which);
2508             }
2509         }
2510         return net;
2511     }
2512 
2513     // ================================================================================
2514     // Always called from UI thread
2515     // ================================================================================
2516 
dump(FileDescriptor fd, PrintWriter pw, String[] args)2517     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2518         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2519         boolean proto = false;
2520         for (int i = 0; i < args.length; i++) {
2521             if ("--proto".equals(args[i])) {
2522                 proto = true;
2523             }
2524         }
2525         if (proto) {
2526             if (mBar == null)  return;
2527             try (TransferPipe tp = new TransferPipe()) {
2528                 // Sending the command to the remote, which needs to execute async to avoid blocking
2529                 // See Binder#dumpAsync() for inspiration
2530                 mBar.dumpProto(args, tp.getWriteFd());
2531                 // Times out after 5s
2532                 tp.go(fd);
2533             } catch (Throwable t) {
2534                 Slog.e(TAG, "Error sending command to IStatusBar", t);
2535             }
2536             return;
2537         }
2538 
2539         synchronized (mLock) {
2540             for (int i = 0; i < mDisplayUiState.size(); i++) {
2541                 final int key = mDisplayUiState.keyAt(i);
2542                 final UiState state = mDisplayUiState.get(key);
2543                 pw.println("  displayId=" + key);
2544                 pw.println("    mDisabled1=0x" + Integer.toHexString(state.getDisabled1()));
2545                 pw.println("    mDisabled2=0x" + Integer.toHexString(state.getDisabled2()));
2546             }
2547             final int N = mDisableRecords.size();
2548             pw.println("  mDisableRecords.size=" + N);
2549             for (int i=0; i<N; i++) {
2550                 DisableRecord tok = mDisableRecords.get(i);
2551                 pw.println("    [" + i + "] " + tok);
2552             }
2553             pw.println("  mCurrentUserId=" + mCurrentUserId);
2554             pw.println("  mIcons=");
2555             for (String slot : mIcons.keySet()) {
2556                 pw.println("    ");
2557                 pw.print(slot);
2558                 pw.print(" -> ");
2559                 final StatusBarIcon icon = mIcons.get(slot);
2560                 pw.print(icon);
2561                 if (!TextUtils.isEmpty(icon.contentDescription)) {
2562                     pw.print(" \"");
2563                     pw.print(icon.contentDescription);
2564                     pw.print("\"");
2565                 }
2566                 pw.println();
2567             }
2568             ArrayList<String> requests;
2569             synchronized (mCurrentRequestAddTilePackages) {
2570                 requests = new ArrayList<>(mCurrentRequestAddTilePackages.keySet());
2571             }
2572             pw.println("  mCurrentRequestAddTilePackages=[");
2573             final int reqN = requests.size();
2574             for (int i = 0; i < reqN; i++) {
2575                 pw.println("    " + requests.get(i) + ",");
2576             }
2577             pw.println("  ]");
2578             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
2579             mTileRequestTracker.dump(fd, ipw.increaseIndent(), args);
2580         }
2581     }
2582 
getUiContext()2583     private static final Context getUiContext() {
2584         return ActivityThread.currentActivityThread().getSystemUiContext();
2585     }
2586 }
2587