Notification framework層的處理流程分析

來源:互聯網
上載者:User

google了一段時間發現沒人寫notification在framework中具體怎麼實現的,感到很奇怪,是我搜尋有問題?哎,不管了,反正工作需要,自己琢磨琢磨吧。
 
 
相關檔案:
  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中:
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方法示範:
Java代碼 
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的執行個體
Java代碼 
volatile IStatusBar mBar; 
 為了防止NPE,每次使用mBar都先判斷是否為null,mBar是在方法registerStatusBar中傳遞進來的。
Java代碼 
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中:
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中:
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為例:
 
Java代碼 
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的具體處理方法。
  摘取部分程式碼片段看看:
 
 
Java代碼 
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了。
 
 
Java代碼 
/** @hide */ 
    static public INotificationManager getService() 
    { 
        if (sService != null) { 
            return sService; 
        } 
        IBinder b = ServiceManager.getService("notification"); 
        sService = INotificationManager.Stub.asInterface(b); 
        return sService; 
    } 
 再看看更熟悉的notify方法,其實是執行:
 
Java代碼 
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) { 
        } 
    } 
 service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);也就是3中提到的那個對外公開的服務方法了,這樣就進入了上面提到的處理流程了。

作者“空之境界”
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.