第二节 Framework UEvent -> SystemUI
逻辑主要在Framework里面的NotificationManagerService.java
UsbDeviceManager.java 到framework的NotificationManagerService.java,这里面涉及到通知的分类和排序,通知的显示风格等等,然后通过NotificationListenerService来通知SystemUI.
在SystemUI注册服务,然后在framework层回调,贯通SystemUI以及Framework。
UsbDeviceManager.java中——》
mNotificationManager.notifyAsUser(null, id, notification,
UserHandle.ALL);
调用NotificationManager的notifyAsUser()往上上传notification,跟到方法里面看下,
路径:framework/base/core/java/android/app/NotificationManager.java
INotificationManager service = getService();//获取IBinder对象
我们看下Notification的addFieldsFromContext方法做了哪些事情:
路径:frameworks/base/core/java/android/app/Notification.java
public static void addFieldsFromContext(Context context, Notification notification) {
addFieldsFromContext(context.getApplicationInfo(), context.getUserId(), notification);
}
/**
* @hide
*/
public static void addFieldsFromContext(ApplicationInfo ai, int userId,
Notification notification) {
notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, ai);//"android.appinfo"
notification.extras.putInt(EXTRA_ORIGINATING_USERID, userId);//"android.originatingUserId"
}
addFieldsFromContext方法主要实现将当前应用的ApplicationInfo对象保存到“android.appinfo”字段,将当前的userId保存到“android.originatingUserId”字段中。
fixLegacySmalIcon,notify函数会判断notification是否有small icon,如果没有设icon或small icon,用notify方法时会抛出异常。fixLegacySmallIcon方法如下:
private void fixLegacySmallIcon(Notification n, String pkg) {
if (n.getSmallIcon() == null && n.icon != 0) {
n.setSmallIcon(Icon.createWithResource(pkg, n.icon));
}
}
完成上面的操作后,调用通知管理类NotificationManagerService的enqueueNotificationWithTag方法,
@Override
public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
Notification notification, int[] idOut, int userId) throws RemoteException {
enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
Binder.getCallingPid(), tag, id, notification, idOut, userId);
}
我们看到在enqueueNotificationWithTag方法中调用了enqueueNotificationInternal方法,这里就是通知处理的核心了。
[java] view plain copy
在CODE上查看代码片派生到我的代码片
void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
int[] idOut, int incomingUserId) {
if (DBG) {
Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
+ " notification=" + notification);
}
checkCallerIsSystemOrSameApp(pkg);
// 校验UID
final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg));
final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg);
final int userId = ActivityManager.handleIncomingUser(callingPid,
callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
final UserHandle user = new UserHandle(userId);
// Fix the notification as best we can.
try {
final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfoAsUser(
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
(userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
Notification.addFieldsFromContext(ai, userId, notification);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Cannot create a context for sending app", e);
return;
}
mUsageStats.registerEnqueuedByApp(pkg);
// Limit the number of notifications that any given package except the android
// package or a registered listener can enqueue. Prevents DOS attacks and de