• 深入理解Notification机制


       framework/base/core/java/android/app/NotificationManager.java

           framework/base/services/java/com/android/server/NotificationManagerService.java{@hide} extends INotificationManager.Stub

           framework/base/services/java/com/android/server/StatusBarManagerService.java  extends IStatusBarService.Stub

           framework/base/core/java/com/android/internal/statusbar/StatusBarNotification  implements Parcelable

           framework/base/core/java/com/android/internal/statusbar/IStatusBar.aidl

            framework/base/core/java/com/android/internal/statusbar/IStatusBarService.aidl

           framework/base/core/java/com/android/internal/statusbar/StatusBarNotification.aidl   

           framework/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java extends Service implements CommandQueue.Callbacks

           framework/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java extends IStatusBar.Stub

    1>.系统启动的时候:framework/base/services/java/com/android/server/SystemServer.java中:

    复制代码
    try {   
            Slog.i(TAG, "Status Bar");     
            statusBar = new StatusBarManagerService(context);   
            ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);   
    } catch (Throwable e) {   
             Slog.e(TAG, "Failure starting StatusBarManagerService", e);   
    }   
                
    try {   
            Slog.i(TAG, "Notification Manager");   
             notification = new NotificationManagerService(context, statusBar, lights);   
                              
             ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);   
    } catch (Throwable e) {   
             Slog.e(TAG, "Failure starting Notification Manager", e);   
    }  
    复制代码

    这段代码是注册状态栏管理和通知管理这两个服务。

    2>.在StatusBarManagerService.java中,有addNotification,removeNotification,updateNotification等方法用于管理传递给他的通知对象。这个类是一些管理方法,实际执行相关动作的是在IStatusBar.java里面,这个是framework/base/core/java/com/android/internal/statusbar/IStatusBar.aidl自动生成的用于IPC的类。

    拿addNotification方法示范:

    复制代码
    public IBinder addNotification(StatusBarNotification notification) {   
                    synchronized (mNotifications) {   
                    IBinder key = new Binder();   
                    mNotifications.put(key, notification);   
                    if (mBar != null) {   
                    try {   
                        mBar.addNotification(key, notification);   
                      } catch (RemoteException ex) {   
                   }   
                }   
                return key;   
            }   
          }  
    复制代码

    这里的mBar其实就是IStatusBar的实例

    volatile IStatusBar mBar;  

    为了防止NPE,每次使用mBar都先判断是否为null,mBar是在方法registerStatusBar中传递进来的。

    复制代码
    public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,   
                List<IBinder> notificationKeys, List<StatusBarNotification> notifications) {   
            enforceStatusBarService();   
        
            Slog.i(TAG, "registerStatusBar bar=" + bar);   
            mBar = bar;   
            synchronized (mIcons) {   
                iconList.copyFrom(mIcons);   
            }   
            synchronized (mNotifications) {   
                for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {   
                    notificationKeys.add(e.getKey());   
                    notifications.add(e.getValue());   
                }   
            }   
            }  
    复制代码
    framework/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java实现IStatusBar.java接口,
    framework/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java提供IStatusBar相关服务。
     
    CommandQueue.java中,IStatusBar.java里面对应的方法是用callback的形式调用的,callback的实现当然就在对应的服务提供类也就是StatusBarService.java中提供的啦。
    CommandQueue.java中:
    复制代码
    public void addNotification(IBinder key, StatusBarNotification notification) {   
            synchronized (mList) {   
                NotificationQueueEntry ne = new NotificationQueueEntry();   
                ne.key = key;   
                ne.notification = notification;   
                mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, ne).sendToTarget();   
                    //这句话对应的mHandler执行语句是:   
                    //  final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;   
                // mCallbacks.addNotification(ne.key, ne.notification);   
                    //也就是调用回调函数里面的addNotification。   
            }   
        }     
    复制代码

    在StatusBarService.java中:

    复制代码
    mCommandQueue = new CommandQueue(this, iconList);//StatusBarService实现了CommandQueue中的CommandQueue.Callbacks接口   
            mBarService = IStatusBarService.Stub.asInterface(   
                    ServiceManager.getService(Context.STATUS_BAR_SERVICE));   
            try {   
                    //将IStatusBar实现类的对象传递到StatusBarManagerService.java中,这里的mCommandQueue就是上面对应的mBar啦。   
                mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications);   
            } catch (RemoteException ex) {   
                // If the system process isn't there we're doomed anyway.   
            }  
    复制代码

    最终执行状态栏更新通知等事件都是在实现的CommandQueue.Callbacks里面执行。还是以addNotification为例:

    复制代码
    public void addNotification(IBinder key, StatusBarNotification notification) {   
            boolean shouldTick = true;   
            if (notification.notification.fullScreenIntent != null) {   
                shouldTick = false;   
                Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");   
                try {   
                    notification.notification.fullScreenIntent.send();   
                } catch (PendingIntent.CanceledException e) {   
                }   
            }    
        
            StatusBarIconView iconView = addNotificationViews(key, notification);   
            if (iconView == null) return;   
              //。。。以下省略N字。  
    复制代码

    大致流程就是:调用StatusBarManagerService.java中的addNotification方法->(mBar不为空的话)执行mBar.addNotification(key, notification);->对应的是CommandQueue中的addNotification(IBinder key, StatusBarNotification notification)->CommandQueue中的mCallbacks.addNotification(ne.key, ne.notification);->StatusBarService中的addNotification。

    3>.上面是提供相关功能的一些类,具体的notification的管理类是framework/base/services/java/com/android/server/NotificationManagerService.java,从该类的定义public class NotificationManagerService extends INotificationManager.Stub可以知道

    他是用来实现接口中INotificationManager中定义的相关方法并向外部提供服务的类。主要向外提供public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,int[] idOut)方法。该方法实际上是调用public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,String tag, int id, Notification notification, int[] idOut),他里面提供了notification的具体处理方法。

     摘取部分代码片段看看:

    复制代码
    if (notification.icon != 0) {   
                    StatusBarNotification n = new StatusBarNotification(pkg, id, tag,   
                            r.uid, r.initialPid, notification);   
                    if (old != null && old.statusBarKey != null) {   
                        r.statusBarKey = old.statusBarKey;   
                        long identity = Binder.clearCallingIdentity();   
                        try {   
                            mStatusBar.updateNotification(r.statusBarKey, n);   
                        }   
                        finally {   
                            Binder.restoreCallingIdentity(identity);   
                        }   
                    } else {   
                        //省略。。。  
    复制代码

    当判断好需要更新通知的时候调用mStatusBar.updateNotification(r.statusBarKey, n);方法,这个就是StatusBarManagerService.java中的addNotification方法,这样就进入上面所说的处理流程了。

    4>. 在3中的NotificationManagerService.java是管理notification的服务,服务嘛就是用来调用的,调用他的就是大家熟悉的NotificationManager了。

    在NotificationManager.java中,有一个隐藏方法,用来得到INotificationManager接口对应的服务提供类,也就是NotificationManagerService了。

    复制代码
    /** @hide */  
        static public INotificationManager getService()   
        {   
            if (sService != null) {   
                return sService;   
            }   
            IBinder b = ServiceManager.getService("notification");   
            sService = INotificationManager.Stub.asInterface(b);   
            return sService;   
        }  
    复制代码

    再看看更熟悉的notify方法,其实是执行:

    复制代码
    public void notify(String tag, int id, Notification notification)   
        {   
            int[] idOut = new int[1];   
            INotificationManager service = getService();   
            String pkg = mContext.getPackageName();   
            if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");   
            try {   
                service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);   
                if (id != idOut[0]) {   
                    Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);   
                }   
            } catch (RemoteException e) {   
            }   
        }  
    复制代码

    ervice.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);也就是3中提到的那个对外公开的服务方法了,这样就进入了上面提到的处理流程了。

     
     
  • 相关阅读:
    Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded datasource could be auto-configured.
    Spring NoSuchBeanDefinitionException六大原因总结
    深入分析Spring 与 Spring MVC容器
    MyBatis mapper parameterType
    eclipse下的mybatis插件:MyBatipse
    javax.servlet-api 和 servlet-api 区别
    Spring中ClassPathXmlApplication与FileSystemXmlApplicationContext的区别
    dump总结
    操作系统基础知识
    JMM中的Happens-Before原则
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2662003.html
Copyright © 2020-2023  润新知