/** * Post a notification to be shown in the status bar. If a notification with * the same tag and id has already been posted by your application and has not yet been * canceled, it will be replaced by the updated information. * * @param tag A string identifier for this notification. May be {@code null}. * @param id An identifier for this notification. The pair (tag, id) must be unique * within your application. * @param notification A {@link Notification} object describing what to * show the user. Must not be null. */ publicvoidnotify(String tag, int id, Notification notification) { notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId())); }
voidenqueueNotificationInternal(final String pkg, final String opPkg, finalint callingUid, finalint callingPid, final String tag, finalint id, final Notification notification, int incomingUserId){ ... // 权限,pid,重复 等检查 mHandler.post(new EnqueueNotificationRunnable(userId, r)); }
protectedclassEnqueueNotificationRunnableimplementsRunnable{ ... @Override publicvoidrun(){ synchronized (mNotificationLock) { ... // tell the assistant service about the notification if (mAssistants.isEnabled()) { mAssistants.onNotificationEnqueued(r); mHandler.postDelayed(new PostNotificationRunnable(r.getKey()), DELAY_FOR_ASSISTANT_TIME); } else { mHandler.post(new PostNotificationRunnable(r.getKey())); } } } } }
protectedclassPostNotificationRunnableimplementsRunnable{ ... @Override publicvoidrun(){ synchronized (mNotificationLock) { ... NotificationRecord old = mNotificationsByKey.get(key); final StatusBarNotification n = r.sbn; final Notification notification = n.getNotification(); int index = indexOfNotificationLocked(n.getKey()); if (index < 0) { mNotificationList.add(r); mUsageStats.registerPostedByApp(r); } else { old = mNotificationList.get(index); mNotificationList.set(index, r); mUsageStats.registerUpdatedByApp(r, old); // Make sure we don't lose the foreground service state. notification.flags |= old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE; r.isUpdate = true; }
mNotificationsByKey.put(n.getKey(), r);
// Ensure if this is a foreground service that the proper additional // flags are set. if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) { notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; }
/** * Register a listener binder directly with the notification manager. * * Only works with system callers. Apps should extend * {@link android.service.notification.NotificationListenerService}. */ @Override publicvoidregisterListener(final INotificationListener listener, final ComponentName component, finalint userid){ enforceSystemOrSystemUI("INotificationManager.registerListener"); mListeners.registerService(listener, component, userid); }
privatefinal NotificationListenerWithPlugins mNotificationListener = new NotificationListenerWithPlugins() { @Override publicvoidonListenerConnected(){ if (DEBUG) Log.d(TAG, "onListenerConnected"); onPluginConnected(); final StatusBarNotification[] notifications = getActiveNotifications(); if (notifications == null) { Log.w(TAG, "onListenerConnected unable to get active notifications."); return; } final RankingMap currentRanking = getCurrentRanking(); mHandler.post(new Runnable() { @Override publicvoidrun(){ for (StatusBarNotification sbn : notifications) { try { addNotification(sbn, currentRanking); } catch (InflationException e) { handleInflationException(sbn, e); } } } }); }
@Override publicvoidonNotificationPosted(final StatusBarNotification sbn, final RankingMap rankingMap){ if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn); if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) { mHandler.post(new Runnable() { @Override publicvoidrun(){ processForRemoteInput(sbn.getNotification()); String key = sbn.getKey(); mKeysKeptForRemoteInput.remove(key); boolean isUpdate = mNotificationData.get(key) != null; // In case we don't allow child notifications, we ignore children of // notifications that have a summary, since we're not going to show them // anyway. This is true also when the summary is canceled, // because children are automatically canceled by NoMan in that case. if (!ENABLE_CHILD_NOTIFICATIONS && mGroupManager.isChildInGroupWithSummary(sbn)) { if (DEBUG) { Log.d(TAG, "Ignoring group child due to existing summary: " + sbn); }
//PhoneWindowManager::beginLayoutLw() publicvoidbeginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, int displayRotation, int uiMode){ ... if (isDefaultDisplay) { // For purposes of putting out fake window up to steal focus, we will // drive nav being hidden only by whether it is requested. finalint sysui = mLastSystemUiFlags; boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; boolean navTranslucent = (sysui & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; boolean navAllowedHidden = immersive || immersiveSticky; navTranslucent &= !immersiveSticky; // transient trumps translucent boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded; if (!isKeyguardShowing) { navTranslucent &= areTranslucentBarsAllowed(); } boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null && mStatusBar.getAttrs().height == MATCH_PARENT && mStatusBar.getAttrs().width == MATCH_PARENT;
// When the navigation bar isn't visible, we put up a fake // input window to catch all touch events. This way we can // detect when the user presses anywhere to bring back the nav // bar and ensure the application doesn't see the event. if (navVisible || navAllowedHidden) { if (mInputConsumer != null) { mHandler.sendMessage( mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); mInputConsumer = null; } } elseif (mInputConsumer == null) { mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(), INPUT_CONSUMER_NAVIGATION, (channel, looper) -> new HideNavInputEventReceiver(channel, looper)); // As long as mInputConsumer is active, hover events are not dispatched to the app // and the pointer icon is likely to become stale. Hide it to avoid confusion. InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL); }
// For purposes of positioning and showing the nav bar, if we have // decided that it can't be hidden (because of the screen aspect ratio), // then take that into account. navVisible |= !canHideNavigationBar();