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中提到的那個對外公開的服務方法瞭,這樣就進入瞭上面提到的處理流程瞭。
作者“空之境界”