前言
在Android系统中,其他模块想要和SystemUI模块交互,基本都离不开StatusBarManagerService这个服务的,StatusBarManagerService顾名思义,就是状态栏管理服务,但其实这个服务不单单可以管理系统状态栏,通过这个服务,我们可以管理SystemUI模块的大部分系统栏组件,比如状态栏、导航栏、最近任务等,本篇文章我们先来简单认识一下这个服务。
一、SystemServer创建StatusBarManagerService服务
1、和大部分系统服务一样,StatusBarManagerService服务也是在SystemServer中被创建:
frameworks/base/service/java/com/android/server/SystemServer.java
public final class SystemServer {public static void main(String[] args) {new SystemServer().run();}private void run() {...代码省略...try {traceBeginAndSlog("StartServices");startBootstrapServices();//启动引导服务startCoreServices();//启动核心服务startOtherServices();//启动其他服务SystemServerInitThreadPool.shutdown();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {traceEnd();}...代码省略...}
}
2、startOtherServices方法和WindowManagerService服务启动相关的代码如下所示。
public final class SystemServer {private ActivityManagerService mActivityManagerService;private boolean mOnlyCore;private boolean mFirstBoot;private void startOtherServices() {...代码省略...StatusBarManagerService statusBar = null;...代码省略...boolean isWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);...代码省略... if (!isWatch) {traceBeginAndSlog("StartStatusBarManagerService");try {//系统栏管理服务statusBar = new StatusBarManagerService(context, wm);ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);} catch (Throwable e) {reportWtf("starting StatusBarManagerService", e);}traceEnd();}...代码省略... }
}
二、StatusBarManagerService类定义
2.1 构造方法
frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
public class StatusBarManagerService extends IStatusBarService.Stub implements DisplayListener {/*** 构造方法*/public StatusBarManagerService(Context context) {mContext = context;LocalServices.addService(StatusBarManagerInternal.class, mInternalService);LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);// We always have a default display.final UiState state = new UiState();mDisplayUiState.put(DEFAULT_DISPLAY, state);final DisplayManager displayManager =(DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);displayManager.registerDisplayListener(this, mHandler);mActivityTaskManager = LocalServices.getService(ActivityTaskManagerInternal.class);}}
2.2 继承的父类
StatusBarManagerService继承自IStatusBarService.Stub,IStatusBarService.aidl文件如下所示。
frameworks/base/core/java/com/android/internal/statusbar/IStatusBarService.aidl
interface IStatusBarService
{@UnsupportedAppUsagevoid expandNotificationsPanel();@UnsupportedAppUsagevoid collapsePanels();void togglePanel();@UnsupportedAppUsagevoid disable(int what, IBinder token, String pkg);void disableForUser(int what, IBinder token, String pkg, int userId);void disable2(int what, IBinder token, String pkg);void disable2ForUser(int what, IBinder token, String pkg, int userId);int[] getDisableFlags(IBinder token, int userId);void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);@UnsupportedAppUsagevoid setIconVisibility(String slot, boolean visible);@UnsupportedAppUsagevoid removeIcon(String slot);void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,boolean showImeSwitcher, boolean isMultiClientImeEnabled);void expandSettingsPanel(String subPanel);// ---- Methods below are for use by the status bar policy services ----// You need the STATUS_BAR_SERVICE permissionRegisterStatusBarResult registerStatusBar(IStatusBar callbacks);void onPanelRevealed(boolean clearNotificationEffects, int numItems);void onPanelHidden();// Mark current notifications as "seen" and stop ringing, vibrating, blinking.void clearNotificationEffects();void onNotificationClick(String key, in NotificationVisibility nv);void onNotificationActionClick(String key, int actionIndex, in Notification.Action action, in NotificationVisibility nv, boolean generatedByAssistant);void onNotificationError(String pkg, String tag, int id,int uid, int initialPid, String message, int userId);void onClearAllNotifications(int userId);void onNotificationClear(String pkg, int userId, String key,int dismissalSurface, int dismissalSentiment, in NotificationVisibility nv);void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,in NotificationVisibility[] noLongerVisibleKeys);void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded, in int notificationLocation);void onNotificationDirectReplied(String key);void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount,boolean generatedByAsssistant, boolean editBeforeSending);void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply,in int notificationLocation, boolean modifiedBeforeSending);void onNotificationSettingsViewed(String key);void onNotificationBubbleChanged(String key, boolean isBubble, int flags);void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed, boolean isBubbleSuppressed);void hideCurrentInputMethodForBubbles();void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);void clearInlineReplyUriPermissions(String key);void onNotificationFeedbackReceived(String key, in Bundle feedback);void onGlobalActionsShown();void onGlobalActionsHidden();/*** These methods are needed for global actions control which the UI is shown in sysui.*/void shutdown();void reboot(boolean safeMode);void addTile(in ComponentName tile);void remTile(in ComponentName tile);void clickTile(in ComponentName tile);@UnsupportedAppUsagevoid handleSystemKey(in int key);/*** Methods to show toast messages for screen pinning*/void showPinningEnterExitToast(boolean entering);void showPinningEscapeToast();// Used to show the authentication dialog (Biometrics, Device Credential)void showAuthenticationDialog(in PromptInfo promptInfo, IBiometricSysuiReceiver sysuiReceiver,in int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,int userId, long operationId, String opPackageName, long requestId,int multiSensorConfig);// Used to notify the authentication dialog that a biometric has been authenticatedvoid onBiometricAuthenticated();// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etcvoid onBiometricHelp(int modality, String message);// Used to show an error - the dialog will dismiss after a certain amount of timevoid onBiometricError(int modality, int error, int vendorCode);// Used to hide the authentication dialog, e.g. when the application cancels authenticationvoid hideAuthenticationDialog();/*** Sets an instance of IUdfpsHbmListener for UdfpsController.*/void setUdfpsHbmListener(in IUdfpsHbmListener listener);/*** Show a warning that the device is about to go to sleep due to user inactivity.*/void showInattentiveSleepWarning();/*** Dismiss the warning that the device is about to go to sleep due to user inactivity.*/void dismissInattentiveSleepWarning(boolean animated);/*** Notifies SystemUI to start tracing.*/void startTracing();/*** Notifies SystemUI to stop tracing.*/void stopTracing();/*** Returns whether SystemUI tracing is enabled.*/boolean isTracing();/*** If true, suppresses the ambient display from showing. If false, re-enables the ambient* display.*/void suppressAmbientDisplay(boolean suppress);}
2.3 实现的接口
StatusBarManagerService实现了DisplayListener,该接口如下所示。
frameworks/base/core/java/android/hardware/display/DisplayManager.java
public final class DisplayManager {/*** Listens for changes in available display devices.*/public interface DisplayListener {/*** Called whenever a logical display has been added to the system.* Use {@link DisplayManager#getDisplay} to get more information about* the display.** @param displayId The id of the logical display that was added.*/void onDisplayAdded(int displayId);/*** Called whenever a logical display has been removed from the system.** @param displayId The id of the logical display that was removed.*/void onDisplayRemoved(int displayId);/*** Called whenever the properties of a logical {@link android.view.Display},* such as size and density, have changed.** @param displayId The id of the logical display that changed.*/void onDisplayChanged(int displayId);}
}
2.4 常用属性
public class StatusBarManagerService extends IStatusBarService.Stub implements DisplayListener {private final Context mContext;private final Handler mHandler = new Handler();private NotificationDelegate mNotificationDelegate;private volatile IStatusBar mBar;private final ArrayMap<String, StatusBarIcon> mIcons = new ArrayMap<>();// for disabling the status barprivate final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();private GlobalActionsProvider.GlobalActionsListener mGlobalActionListener;private final IBinder mSysUiVisToken = new Binder();private final Object mLock = new Object();private final DeathRecipient mDeathRecipient = new DeathRecipient();private final ActivityTaskManagerInternal mActivityTaskManager;private int mCurrentUserId;private boolean mTracingEnabled;private final SparseArray<UiState> mDisplayUiState = new SparseArray<>();@GuardedBy("mLock")private IUdfpsHbmListener mUdfpsHbmListener;/*** Private API used by NotificationManagerService.*/private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {private boolean mNotificationLightOn;@Overridepublic void setNotificationDelegate(NotificationDelegate delegate) {mNotificationDelegate = delegate;}@Overridepublic void showScreenPinningRequest(int taskId) {if (mBar != null) {try {mBar.showScreenPinningRequest(taskId);} catch (RemoteException e) {}}}@Overridepublic void showAssistDisclosure() {if (mBar != null) {try {mBar.showAssistDisclosure();} catch (RemoteException e) {}}}@Overridepublic void startAssist(Bundle args) {if (mBar != null) {try {mBar.startAssist(args);} catch (RemoteException e) {}}}@Overridepublic void onCameraLaunchGestureDetected(int source) {if (mBar != null) {try {mBar.onCameraLaunchGestureDetected(source);} catch (RemoteException e) {}}}/*** Notifies the status bar that a Emergency Action launch gesture has been detected.** TODO (b/169175022) Update method name and docs when feature name is locked.*/@Overridepublic void onEmergencyActionLaunchGestureDetected() {if (SPEW) Slog.d(TAG, "Launching emergency action");if (mBar != null) {try {mBar.onEmergencyActionLaunchGestureDetected();} catch (RemoteException e) {if (SPEW) Slog.d(TAG, "Failed to launch emergency action");}}}@Overridepublic void setDisableFlags(int displayId, int flags, String cause) {StatusBarManagerService.this.setDisableFlags(displayId, flags, cause);}@Overridepublic void toggleSplitScreen() {enforceStatusBarService();if (mBar != null) {try {mBar.toggleSplitScreen();} catch (RemoteException ex) {}}}@Overridepublic void appTransitionFinished(int displayId) {enforceStatusBarService();if (mBar != null) {try {mBar.appTransitionFinished(displayId);} catch (RemoteException ex) {}}}@Overridepublic void toggleRecentApps() {if (mBar != null) {try {mBar.toggleRecentApps();} catch (RemoteException ex) {}}}@Overridepublic void setCurrentUser(int newUserId) {if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);mCurrentUserId = newUserId;}@Overridepublic void preloadRecentApps() {if (mBar != null) {try {mBar.preloadRecentApps();} catch (RemoteException ex) {}}}@Overridepublic void cancelPreloadRecentApps() {if (mBar != null) {try {mBar.cancelPreloadRecentApps();} catch (RemoteException ex) {}}}@Overridepublic void showRecentApps(boolean triggeredFromAltTab) {if (mBar != null) {try {mBar.showRecentApps(triggeredFromAltTab);} catch (RemoteException ex) {}}}@Overridepublic void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {if (mBar != null) {try {mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey);} catch (RemoteException ex) {}}}@Overridepublic void collapsePanels() {if (mBar != null) {try {mBar.animateCollapsePanels();} catch (RemoteException ex) {}}}@Overridepublic void dismissKeyboardShortcutsMenu() {if (mBar != null) {try {mBar.dismissKeyboardShortcutsMenu();} catch (RemoteException ex) {}}}@Overridepublic void toggleKeyboardShortcutsMenu(int deviceId) {if (mBar != null) {try {mBar.toggleKeyboardShortcutsMenu(deviceId);} catch (RemoteException ex) {}}}@Overridepublic void showChargingAnimation(int batteryLevel) {if (mBar != null) {try {mBar.showWirelessChargingAnimation(batteryLevel);} catch (RemoteException ex){}}}@Overridepublic void showPictureInPictureMenu() {if (mBar != null) {try {mBar.showPictureInPictureMenu();} catch (RemoteException ex) {}}}@Overridepublic void setWindowState(int displayId, int window, int state) {if (mBar != null) {try {mBar.setWindowState(displayId, window, state);} catch (RemoteException ex) {}}}@Overridepublic void appTransitionPending(int displayId) {if (mBar != null) {try {mBar.appTransitionPending(displayId);} catch (RemoteException ex) {}}}@Overridepublic void appTransitionCancelled(int displayId) {if (mBar != null) {try {mBar.appTransitionCancelled(displayId);} catch (RemoteException ex) {}}}@Overridepublic void appTransitionStarting(int displayId, long statusBarAnimationsStartTime,long statusBarAnimationsDuration) {if (mBar != null) {try {mBar.appTransitionStarting(displayId, statusBarAnimationsStartTime, statusBarAnimationsDuration);} catch (RemoteException ex) {}}}@Overridepublic void setTopAppHidesStatusBar(boolean hidesStatusBar) {if (mBar != null) {try {mBar.setTopAppHidesStatusBar(hidesStatusBar);} catch (RemoteException ex) {}}}@Overridepublic boolean showShutdownUi(boolean isReboot, String reason) {if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) {return false;}if (mBar != null) {try {mBar.showShutdownUi(isReboot, reason);return true;} catch (RemoteException ex) {}}return false;}// TODO(b/118592525): support it per display if necessary.@Overridepublic void onProposedRotationChanged(int rotation, boolean isValid) {if (mBar != null){try {mBar.onProposedRotationChanged(rotation, isValid);} catch (RemoteException ex) {}}}@Overridepublic void onDisplayReady(int displayId) {if (mBar != null) {try {mBar.onDisplayReady(displayId);} catch (RemoteException ex) {}}}@Overridepublic void onRecentsAnimationStateChanged(boolean running) {if (mBar != null) {try {mBar.onRecentsAnimationStateChanged(running);} catch (RemoteException ex) {}}}@Overridepublic void onSystemBarAttributesChanged(int displayId, @Appearance int appearance,AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme,@Behavior int behavior, InsetsVisibilities requestedVisibilities,String packageName) {getUiState(displayId).setBarAttributes(appearance, appearanceRegions,navbarColorManagedByIme, behavior, requestedVisibilities, packageName);if (mBar != null) {try {mBar.onSystemBarAttributesChanged(displayId, appearance, appearanceRegions,navbarColorManagedByIme, behavior, requestedVisibilities, packageName);} catch (RemoteException ex) { }}}@Overridepublic void showTransient(int displayId, @InternalInsetsType int[] types,boolean isGestureOnSystemBar) {getUiState(displayId).showTransient(types);if (mBar != null) {try {mBar.showTransient(displayId, types, isGestureOnSystemBar);} catch (RemoteException ex) { }}}@Overridepublic void abortTransient(int displayId, @InternalInsetsType int[] types) {getUiState(displayId).clearTransient(types);if (mBar != null) {try {mBar.abortTransient(displayId, types);} catch (RemoteException ex) { }}}@Overridepublic void showToast(int uid, String packageName, IBinder token, CharSequence text,IBinder windowToken, int duration,@Nullable ITransientNotificationCallback callback) {if (mBar != null) {try {mBar.showToast(uid, packageName, token, text, windowToken, duration, callback);} catch (RemoteException ex) { }}}@Overridepublic void hideToast(String packageName, IBinder token) {if (mBar != null) {try {mBar.hideToast(packageName, token);} catch (RemoteException ex) { }}}@Overridepublic void requestWindowMagnificationConnection(boolean request) {if (mBar != null) {try {mBar.requestWindowMagnificationConnection(request);} catch (RemoteException ex) { }}}@Overridepublic void handleWindowManagerLoggingCommand(String[] args, ParcelFileDescriptor outFd) {if (mBar != null) {try {mBar.handleWindowManagerLoggingCommand(args, outFd);} catch (RemoteException ex) { }}}@Overridepublic void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {if (mBar != null) {try {mBar.setNavigationBarLumaSamplingEnabled(displayId, enable);} catch (RemoteException ex) { }}}@Overridepublic void setUdfpsHbmListener(IUdfpsHbmListener listener) {synchronized (mLock) {mUdfpsHbmListener = listener;}if (mBar != null) {try {mBar.setUdfpsHbmListener(listener);} catch (RemoteException ex) { }}}};private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {@Overridepublic boolean isGlobalActionsDisabled() {// TODO(b/118592525): support global actions for multi-display.final int disabled2 = mDisplayUiState.get(DEFAULT_DISPLAY).getDisabled2();return (disabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;}@Overridepublic void setGlobalActionsListener(GlobalActionsProvider.GlobalActionsListener listener) {mGlobalActionListener = listener;mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);}@Overridepublic void showGlobalActions() {if (mBar != null) {try {mBar.showGlobalActionsMenu();} catch (RemoteException ex) {}}}};}