Android 9.0系统源码_通知服务(二)系统状态栏是如何监听通知服务的各种通知事件的
创始人
2025-05-31 04:01:34
0

前言

上一篇文章简单讲述了系统通知服务NotificationManagerService的启动流程,本篇文章我们将会具体梳理一下SystemUI组件系统状态栏StatusBar是如何监听通知服务的各种通知事件的。

一、StatusBar调用NotificationListener的setUpWithPresenter

1、我们在Android 9.0系统源码_SystemUI(一)SystemUI的启动流程系列文章有具体分析过SystemUI的启动流程,在状态栏StatusBar被创建之后,首先触发的便是start方法。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public class StatusBar extends SystemUI implements DemoMode,DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {protected NotificationListener mNotificationListener;protected NotificationEntryManager mEntryManager;@Overridepublic void start() {...代码省略...mNotificationListener =  Dependency.get(NotificationListener.class);mEntryManager = Dependency.get(NotificationEntryManager.class);...代码省略...createAndAddWindows();//创建状态栏并添加到窗口上...代码省略...// Set up the initial notification state.//监听NotificationManagerService的通知消息mNotificationListener.setUpWithPresenter(this, mEntryManager);...代码省略...}}

在start方法中会获取NotificationListener实例对象,并调用该对象的setUpWithPresenter方法。

二、NotificationListener设置通知服务的回调方法。

1、NotificationListener的setUpWithPresenter方法如下所示。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java

public class NotificationListener extends NotificationListenerWithPlugins {private static final String TAG = "NotificationListener";private final Context mContext;protected NotificationPresenter mPresenter;protected NotificationEntryManager mEntryManager;public NotificationListener(Context context) {mContext = context;}@Overridepublic void onListenerConnected() {...连接成功...}@Overridepublic void onNotificationPosted(final StatusBarNotification sbn,final RankingMap rankingMap) {...新的通知...}@Overridepublic void onNotificationRemoved(StatusBarNotification sbn,final RankingMap rankingMap) {...移除通知...}@Overridepublic void onNotificationRankingUpdate(final RankingMap rankingMap) {...更新通知...}public void setUpWithPresenter(NotificationPresenter presenter, NotificationEntryManager entryManager) {mPresenter = presenter;mEntryManager = entryManager;try {registerAsSystemService(mContext, new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()), UserHandle.USER_ALL);} catch (RemoteException e) {Log.e(TAG, "Unable to register notification listener", e);}}
}

NotificationListener自身的各种回调方法会在特定情况下被通知服务所触发,而设置监听通知服务的setUpWithPresenter方法在给mPresenter和mEntryManager赋值之后,会进一步调用父类NotificationListenerWithPlugins的registerAsSystemService方法。

2、NotificationListenerWithPlugins的registerAsSystemService方法如下所示。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java

public class NotificationListenerWithPlugins extends NotificationListenerService implementsPluginListener {@Overridepublic void registerAsSystemService(Context context, ComponentName componentName,int currentUser) throws RemoteException {super.registerAsSystemService(context, componentName, currentUser);Dependency.get(PluginManager.class).addPluginListener(this, NotificationListenerController.class);}
}

3、NotificationListenerWithPlugins会继续调用自己的父类NotificationListenerService的registerAsSystemService方法。

frameworks/base/core/java/android/service/notification/NotificationListenerService.java

public abstract class NotificationListenerService extends Service {protected NotificationListenerWrapper mWrapper = null;protected Context mSystemContext;private Handler mHandler;protected int mCurrentUser;public void registerAsSystemService(Context context, ComponentName componentName,int currentUser) throws RemoteException {if (mWrapper == null) {// 这就是要注册的Binder,也就一个回调mWrapper = new NotificationListenerWrapper();}mSystemContext = context;INotificationManager noMan = getNotificationInterface();mHandler = new MyHandler(context.getMainLooper());mCurrentUser = currentUser;//向通知服务NotificationManagerService注册回调noMan.registerListener(mWrapper, componentName, currentUser);}//获取通知服务protected final INotificationManager getNotificationInterface() {if (mNoMan == null) {mNoMan = INotificationManager.Stub.asInterface(ServiceManager.getService(Context.NOTIFICATION_SERVICE));}return mNoMan;}//回调对象protected class NotificationListenerWrapper extends INotificationListener.Stub {@Overridepublic void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,NotificationRankingUpdate update) {...有通知事件...}@Overridepublic void onListenerConnected(NotificationRankingUpdate update) {...连接成功...}}
}

NotificationListenerService的registerAsSystemService方法首先创建一个类型为NotificationListenerWrapper的mWrapper对象,NotificationListenerWrapper是NotificationListenerService的内部类,该类实现了INotificationListener.Stub,然后会调用getNotificationInterface方法,获取NotificationManagerService对象实例并调用registerListener方法。

5、NotificationManagerService的registerListener方法如下所示。

public class NotificationManagerService extends SystemService {private NotificationListeners mListeners;//主要用于管理通知的接收者void init(Looper looper, IPackageManager packageManager,PackageManager packageManagerClient,LightsManager lightsManager, NotificationListeners notificationListeners,NotificationAssistants notificationAssistants, ConditionProviders conditionProviders,ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,NotificationUsageStats usageStats, AtomicFile policyFile,ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am,UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm) {...代码省略...// This is a ManagedServices object that keeps track of the listeners.mListeners = notificationListeners;...代码省略...}@Overridepublic void registerListener(final INotificationListener listener,final ComponentName component, final int userid) {enforceSystemOrSystemUI("INotificationManager.registerListener");mListeners.registerService(listener, component, userid);}
}

这里的mListeners,其实就是NotificationManagerService的init方法中提到类型为NotificationListeners的mListeners。

6、NotificationListeners是NotificationManagerService的内部类。

public class NotificationManagerService extends SystemService {public class NotificationListeners extends ManagedServices {private final ArraySet mLightTrimListeners = new ArraySet<>();public NotificationListeners(IPackageManager pm) {super(getContext(), mNotificationLock, mUserProfiles, pm);}}
}

7、我们在NotificationListeners类中并不能找到registerService方法,这是因为该方法定义在他的父类ManagedServices中。

frameworks/base/services/core/java/com/android/server/notification/ManagedServices.java

abstract public class ManagedServices {public void registerService(IInterface service, ComponentName component, int userid) {checkNotNull(service);//继续调用registerServiceImplManagedServiceInfo info = registerServiceImpl(service, component, userid);if (info != null) {onServiceAdded(info);}}private ManagedServiceInfo registerServiceImpl(final IInterface service,final ComponentName component, final int userid) {//调用newServiceInfo方法创建ManagedServiceInfo对象实例ManagedServiceInfo info = newServiceInfo(service, component, userid,true /*isSystem*/, null /*connection*/, Build.VERSION_CODES.LOLLIPOP);//将新创建的ManagedServiceInfo作为参数继续调用registerServiceImpl方法。return registerServiceImpl(info);}private ManagedServiceInfo newServiceInfo(IInterface service,ComponentName component, int userId, boolean isSystem, ServiceConnection connection,int targetSdkVersion) {//创建ManagedServiceInfo对象实例return new ManagedServiceInfo(service, component, userId, isSystem, connection,targetSdkVersion);}|

8、ManagedServiceInfo 是 ManagedServices 的内部类。

abstract public class ManagedServices {public class ManagedServiceInfo implements IBinder.DeathRecipient {public IInterface service;//指向的就是前面提到的NotificationListenerWrapper对象,是一个代理对象public ComponentName component;public int userid;public boolean isSystem;public ServiceConnection connection;public int targetSdkVersion;public ManagedServiceInfo(IInterface service, ComponentName component,int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) {this.service = service;this.component = component;this.userid = userid;this.isSystem = isSystem;this.connection = connection;this.targetSdkVersion = targetSdkVersion;}}}       

结合ManagedServiceInfo的构造方法可知,最终时将前面提到的NotificationListenerWrapper对象赋值给了类型为IInterface的变量service,NotificationListenerWrapper是一个代理对象,该对象运行在SystemUI进程中用于接收系统通知。

9、在ManagedServiceInfo 对象创建完毕之后,会继续调用registerServiceImpl方法。

abstract public class ManagedServices {private final ArrayList mServices = new ArrayList<>();private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) {synchronized (mMutex) {try {info.service.asBinder().linkToDeath(info, 0);mServices.add(info);return info;} catch (RemoteException e) {// already dead}}return null;}
}    

由上可知最终将ManagedServiceInfo实例对象存储在了类型为集合mServices中。

10、重新回到前面第7步,在创建完ManagedServiceInfo对象之后,如果创建的ManagedServiceInfo实例对象不为空,则会调用onServiceAdded方法。

abstract public class ManagedServices {private final ArrayList mServices = new ArrayList<>();public void registerService(IInterface service, ComponentName component, int userid) {checkNotNull(service);//继续调用registerServiceImplManagedServiceInfo info = registerServiceImpl(service, component, userid);if (info != null) {onServiceAdded(info);}}abstract protected void onServiceAdded(ManagedServiceInfo info); }

11、onServiceAdded方法是一个抽象方法,具体实现是在前面提到的NotificationManagerService的内部类NotificationListeners中。

public class NotificationManagerService extends SystemService {public class NotificationListeners extends ManagedServices {@Overridepublic void onServiceAdded(ManagedServiceInfo info) {final INotificationListener listener = (INotificationListener) info.service;final NotificationRankingUpdate update;synchronized (mNotificationLock) {update = makeRankingUpdateLocked(info);}try {//注册成功,开始进行回调通知listener.onListenerConnected(update);} catch (RemoteException e) {// we tried}}}
}

绕了这么一大圈,总算是触发INotificationListener的onListenerConnected回调方法了,而INotificationListener的具体实现者我们前面有提到,就是NotificationListenerService的内部类NotificationListenerWrapper。

三、NotificationListener设置回调方法被触发。

1、NotificationListenerService$NotificationListenerWrapper类中和onListenerConnected回调方法相关的代码如下所示。

public abstract class NotificationListenerService extends Service {private Handler mHandler;@Overrideprotected void attachBaseContext(Context base) {super.attachBaseContext(base);mHandler = new MyHandler(getMainLooper());}private final class MyHandler extends Handler {public static final int MSG_ON_LISTENER_CONNECTED = 3;public MyHandler(Looper looper) {super(looper, null, false);}@Overridepublic void handleMessage(Message msg) {if (!isConnected) {return;}switch (msg.what) {...代码省略...case MSG_ON_LISTENER_CONNECTED: {//回调会NotificationListenerService的onListenerConnected方法。onListenerConnected();} break;...代码省略...}}public void onListenerConnected() {...连接成功...}//回调对象protected class NotificationListenerWrapper extends INotificationListener.Stub {@Overridepublic void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,NotificationRankingUpdate update) {...有通知事件...}//和通知服务建立连接成功@Overridepublic void onListenerConnected(NotificationRankingUpdate update) {// protect subclass from concurrent modifications of (@link mNotificationKeys}.Log.d("NotificationListenerService","onListenerConnected exec");synchronized (mLock) {applyUpdateLocked(update);}isConnected = true;//发送消息,触发MyHandler的handleMessage方法。mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget();}}
}

NotificationListenerService$NotificationListenerWrapper的onListenerConnected方法会调用mHandler发送类型为MSG_ON_LISTENER_CONNECTED的消息,该消息会触发MyHandler的handleMessage方法,最终触发NotificationListenerService 类的onListenerConnected方法。由于NotificationListener就是继承自NotificationListenerService的,并且它还重写了onListenerConnected方法,这样回调就来到了它这边。

2、当通知服务NotificationManangerService收到其他的各种通知事件的时候,NotificationListenerWrapper的各个回调方法便会被触发,然后通过类型为MyHandler的mHandler发送对应的消息,进一步触发NotificationListenerService所对应的回调方法,也就是NotificationListener的回调方法。

public class NotificationListener extends NotificationListenerWithPlugins {private static final String TAG = "NotificationListener";private final Context mContext;protected NotificationPresenter mPresenter;protected NotificationEntryManager mEntryManager;public NotificationListener(Context context) {mContext = context;}@Overridepublic void onListenerConnected() {...连接成功...}@Overridepublic void onNotificationPosted(final StatusBarNotification sbn,final RankingMap rankingMap) {if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {// 在主线程中进行更新mPresenter.getHandler().post(() -> {processForRemoteInput(sbn.getNotification(), mContext);String key = sbn.getKey();mEntryManager.removeKeyKeptForRemoteInput(key);boolean isUpdate = mEntryManager.getNotificationData().get(key) != null;// In case we don't allow child notifications, we ignore children of// notifications that have a summary, since` we're not going to show them// anyway. This is true also when the summary is canceled,// because children are automatically canceled by NoMan in that case.if (!ENABLE_CHILD_NOTIFICATIONS&& mPresenter.getGroupManager().isChildInGroupWithSummary(sbn)) {if (DEBUG) {Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);}// Remove existing notification to avoid stale data.if (isUpdate) {mEntryManager.removeNotification(key, rankingMap);} else {mEntryManager.getNotificationData().updateRanking(rankingMap);}return;}//判断到来的通知是需要更新还是添加if (isUpdate) {// 更新通知操作mEntryManager.updateNotification(sbn, rankingMap);} else {// 添加新通知操作mEntryManager.addNotification(sbn, rankingMap);}});}}@Overridepublic void onNotificationRemoved(StatusBarNotification sbn,final RankingMap rankingMap) {...移除通知...}@Overridepublic void onNotificationRankingUpdate(final RankingMap rankingMap) {...更新通知...}public void setUpWithPresenter(NotificationPresenter presenter, NotificationEntryManager entryManager) {mPresenter = presenter;mEntryManager = entryManager;try {registerAsSystemService(mContext, new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()), UserHandle.USER_ALL);} catch (RemoteException e) {Log.e(TAG, "Unable to register notification listener", e);}}
}

四、总结

系统状态栏是如何监听通知服务的各种通知事件的

相关内容

热门资讯

劳动课程学习的心得体会 劳动课程学习的心得体会(通用20篇)  我们从一些事情上得到感悟后,不如来好好地做个总结,写一篇心得...
奥运会志愿者的心得体会 奥运会志愿者的心得体会范文  眨眼间,20xx年奥运会即将结束,在过去的一个半月中,我深深体会到作为...
教师岗前培训的心得体会 教师岗前培训的心得体会(精选22篇)  我们在一些事情上受到启发后,可以寻思将其写进心得体会中,这样...
思修课心得体会 思修课心得体会(通用9篇)  我们得到了一些心得体会以后,可以通过写心得体会的方式将其记录下来,这样...
Self-supervised... Self-supervised Learning: Generative or Contrastiv...
队列及其接口实现(超详解哦) 全文目录引言队列介绍接口实现队列的初始化与销毁判断队列是否为空队尾入队列队头出队列访问队头元素访问队...
【LeetCode】剑指 Of... 题目链接:https://leetcode.cn/problems/er-cha-sh...
银行管理培训心得体会 银行管理培训心得体会(精选13篇)  我们有一些启发后,写一篇心得体会,记录下来,这样有利于培养我们...
幼儿教师暑期培训心得体会 幼儿教师暑期培训心得体会(精选4篇)  当我们备受启迪时,将其记录在心得体会里,让自己铭记于心,这样...
孙瑞雪《爱和自由》读后感 孙瑞雪《爱和自由》读后感还没看过蒙特梭利的原著,先读了这本书。由于是在网上看的电子版,结果好多版本都...
理解对数——了解对数的历史和用... 攻克对数:一瞥对数的历史和用途 Chopping Logs: A Look at th...
达梦数据库的几种模式及状态说明 一、达梦数据库三种模式达梦数据库支持 3 种数据库模式: Normal 模式、 Pri...
UWB芯片DW3000介绍一调... 数据调制方案在IEEE802.15.4标准[1]中规定的超宽带UWB技术有时也被称为脉冲无线电超宽带...
五年级读后感 五年级读后感(精选31篇)  读完一本经典名著后,你心中有什么感想呢?现在就让我们写一篇走心的读后感...
家庭教育读书心得体会 家庭教育读书心得体会  看完一本名著后,相信大家的收获肯定不少,让我们好好写份读书心得,把你的收获和...
《问题背后的问题》读后感 《问题背后的问题》读后感范文(通用25篇)  认真读完一本著作后,你有什么体会呢?不能光会读哦,写一...
最后一头战象读后感300字 最后一头战象读后感范文300字  课文讲述了在战争中幸存下来的一头大象——嘎羧。它自知生命大限以至,...
HBuilderX 安装教程 💌 所属专栏:【软件安装教程】 😀 作  者&#x...
《西厢记》 《西厢记》《西厢记》人物形象浅析——前世的戏文,今生的遗梦如今世人的脚步太匆匆,言情小说出产的速度堪...
目送 [目送]第一篇:《目送》读后感  “目送”两字一入眼帘,便觉得有一条长长的路在眼前展开,过往那些回忆...