1.在syatemUI显示相关通知之前,做了很多的准备工作,这边我们来说说notification的排序。
排序工作主要是在NotificationManagerService.java里面实现的。
路径:frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
我们来看下enqueueNotificationWithTag方法,这里调用了enqueueNotificationInternal方法,这里就是通知处理的核心了。
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 deals with leaks.
// 这里会做一个限制,除了系统级别的应用之外,其他应用的notification数量会做限制,用来防止DOS攻击导致的泄露
if (!isSystemNotification && !isNotificationFromListener) {
synchronized (mNotificationList) {
final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
if (appEnqueueRate > mMaxPackageEnqueueRate) {
mUsageStats.registerOverRateQuota(pkg);
final long now = SystemClock.elapsedRealtime();
if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
+ ". Shedding events. package=" + pkg);
mLastOverRateLogTime = now;
}
return;
}
int count = 0;
final int N = mNotificationList.size();
for (int i=0; i<N; i++) {
final NotificationRecord r = mNotificationList.get(i);
if (r.sbn.getPackageName().equals(pkg) && r.sbn.getUserId() == userId) {
if (r.sbn.getId() == id && TextUtils.equals(r.sbn.getTag(), tag)) {
break; // Allow updating existing notification
}
count++;
if (count >= MAX_PACKAGE_NOTIFICATIONS) {// 同一个应用发送notification数量不能超过50
mUsageStats.registerOverCountQuota(pkg);
Slog.e(TAG, "Package has already posted " + count
+ " notifications. Not showing more. package=" + pkg);
return;
}
}
}
&n