Loading services/java/com/android/server/NotificationManagerService.java +235 −210 Original line number Original line Diff line number Diff line Loading @@ -1601,8 +1601,10 @@ public class NotificationManagerService extends INotificationManager.Stub // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the // uid/pid of another application) // uid/pid of another application) public void enqueueNotificationInternal(String pkg, String basePkg, int callingUid, int callingPid, String tag, int id, Notification notification, int[] idOut, int userId) public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid, final int callingPid, final String tag, final int id, final Notification notification, int[] idOut, int incomingUserId) { { if (DBG) { if (DBG) { Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); Loading @@ -1610,8 +1612,8 @@ public class NotificationManagerService extends INotificationManager.Stub checkCallerIsSystemOrSameApp(pkg); checkCallerIsSystemOrSameApp(pkg); final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg)); final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg)); userId = ActivityManager.handleIncomingUser(callingPid, final int userId = ActivityManager.handleIncomingUser(callingPid, callingUid, userId, true, false, "enqueueNotification", pkg); callingUid, incomingUserId, true, false, "enqueueNotification", pkg); final UserHandle user = new UserHandle(userId); final UserHandle user = new UserHandle(userId); // Limit the number of notifications that any given package except the android // Limit the number of notifications that any given package except the android Loading Loading @@ -1653,15 +1655,25 @@ public class NotificationManagerService extends INotificationManager.Stub } } } } mHandler.post(new Runnable() { @Override public void run() { // === Scoring === // === Scoring === // 0. Sanitize inputs // 0. Sanitize inputs notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX); notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX); // Migrate notification flags to scores // Migrate notification flags to scores if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) { if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) { if (notification.priority < Notification.PRIORITY_MAX) notification.priority = Notification.PRIORITY_MAX; if (notification.priority < Notification.PRIORITY_MAX) { } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) { notification.priority = Notification.PRIORITY_MAX; if (notification.priority < Notification.PRIORITY_HIGH) notification.priority = Notification.PRIORITY_HIGH; } } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) { if (notification.priority < Notification.PRIORITY_HIGH) { notification.priority = Notification.PRIORITY_HIGH; } } } // 1. initial score: buckets of 10, around the app // 1. initial score: buckets of 10, around the app Loading @@ -1675,7 +1687,8 @@ public class NotificationManagerService extends INotificationManager.Stub if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) { if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) { if (!isSystemNotification) { if (!isSystemNotification) { score = JUNK_SCORE; score = JUNK_SCORE; Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); } } } } Loading Loading @@ -1769,7 +1782,8 @@ public class NotificationManagerService extends INotificationManager.Stub } } // ATTENTION: in a future release we will bail out here // ATTENTION: in a future release we will bail out here // so that we do not play sounds, show lights, etc. for invalid notifications // so that we do not play sounds, show lights, etc. for invalid notifications Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName()); Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName()); } } // If we're not supposed to beep, vibrate, etc. then don't. // If we're not supposed to beep, vibrate, etc. then don't. Loading @@ -1786,11 +1800,13 @@ public class NotificationManagerService extends INotificationManager.Stub // sound // sound // should we use the default notification sound? (indicated either by DEFAULT_SOUND // should we use the default notification sound? (indicated either by // or because notification.sound is pointing at Settings.System.NOTIFICATION_SOUND) // DEFAULT_SOUND or because notification.sound is pointing at // Settings.System.NOTIFICATION_SOUND) final boolean useDefaultSound = final boolean useDefaultSound = (notification.defaults & Notification.DEFAULT_SOUND) != 0 (notification.defaults & Notification.DEFAULT_SOUND) != 0 || || Settings.System.DEFAULT_NOTIFICATION_URI.equals(notification.sound); Settings.System.DEFAULT_NOTIFICATION_URI .equals(notification.sound); Uri soundUri = null; Uri soundUri = null; boolean hasValidSound = false; boolean hasValidSound = false; Loading @@ -1816,8 +1832,8 @@ public class NotificationManagerService extends INotificationManager.Stub audioStreamType = DEFAULT_STREAM_TYPE; audioStreamType = DEFAULT_STREAM_TYPE; } } mSoundNotification = r; mSoundNotification = r; // do not play notifications if stream volume is 0 // do not play notifications if stream volume is 0 (typically because // (typically because ringer mode is silent) or if speech recognition is active. // ringer mode is silent) or if speech recognition is active. if ((audioManager.getStreamVolume(audioStreamType) != 0) if ((audioManager.getStreamVolume(audioStreamType) != 0) && !audioManager.isSpeechRecognitionActive()) { && !audioManager.isSpeechRecognitionActive()) { final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading @@ -1837,37 +1853,43 @@ public class NotificationManagerService extends INotificationManager.Stub // Does the notification want to specify its own vibration? // Does the notification want to specify its own vibration? final boolean hasCustomVibrate = notification.vibrate != null; final boolean hasCustomVibrate = notification.vibrate != null; // new in 4.2: if there was supposed to be a sound and we're in vibrate mode, // new in 4.2: if there was supposed to be a sound and we're in vibrate // and no other vibration is specified, we fall back to vibration // mode, and no other vibration is specified, we fall back to vibration final boolean convertSoundToVibration = final boolean convertSoundToVibration = !hasCustomVibrate !hasCustomVibrate && hasValidSound && hasValidSound && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE); && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE); // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. final boolean useDefaultVibrate = final boolean useDefaultVibrate = (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; mVibrateNotification = r; if (useDefaultVibrate || convertSoundToVibration) { if (useDefaultVibrate || convertSoundToVibration) { // Escalate privileges so we can use the vibrator even if the notifying app // Escalate privileges so we can use the vibrator even if the // does not have the VIBRATE permission. // notifying app does not have the VIBRATE permission. long identity = Binder.clearCallingIdentity(); long identity = Binder.clearCallingIdentity(); try { try { mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), useDefaultVibrate ? mDefaultVibrationPattern useDefaultVibrate ? mDefaultVibrationPattern : mFallbackVibrationPattern, : mFallbackVibrationPattern, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); } finally { } finally { Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity); } } } else if (notification.vibrate.length > 1) { } else if (notification.vibrate.length > 1) { // If you want your own vibration pattern, you need the VIBRATE permission // If you want your own vibration pattern, you need the VIBRATE mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, // permission ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); } } } } } } Loading @@ -1879,7 +1901,8 @@ public class NotificationManagerService extends INotificationManager.Stub mLedNotification = null; mLedNotification = null; } } //Slog.i(TAG, "notification.lights=" //Slog.i(TAG, "notification.lights=" // + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) != 0)); // + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) // != 0)); if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && canInterrupt) { && canInterrupt) { mLights.add(r); mLights.add(r); Loading @@ -1891,6 +1914,8 @@ public class NotificationManagerService extends INotificationManager.Stub } } } } } } } }); idOut[0] = id; idOut[0] = id; } } Loading Loading
services/java/com/android/server/NotificationManagerService.java +235 −210 Original line number Original line Diff line number Diff line Loading @@ -1601,8 +1601,10 @@ public class NotificationManagerService extends INotificationManager.Stub // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the // uid/pid of another application) // uid/pid of another application) public void enqueueNotificationInternal(String pkg, String basePkg, int callingUid, int callingPid, String tag, int id, Notification notification, int[] idOut, int userId) public void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid, final int callingPid, final String tag, final int id, final Notification notification, int[] idOut, int incomingUserId) { { if (DBG) { if (DBG) { Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); Loading @@ -1610,8 +1612,8 @@ public class NotificationManagerService extends INotificationManager.Stub checkCallerIsSystemOrSameApp(pkg); checkCallerIsSystemOrSameApp(pkg); final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg)); final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg)); userId = ActivityManager.handleIncomingUser(callingPid, final int userId = ActivityManager.handleIncomingUser(callingPid, callingUid, userId, true, false, "enqueueNotification", pkg); callingUid, incomingUserId, true, false, "enqueueNotification", pkg); final UserHandle user = new UserHandle(userId); final UserHandle user = new UserHandle(userId); // Limit the number of notifications that any given package except the android // Limit the number of notifications that any given package except the android Loading Loading @@ -1653,15 +1655,25 @@ public class NotificationManagerService extends INotificationManager.Stub } } } } mHandler.post(new Runnable() { @Override public void run() { // === Scoring === // === Scoring === // 0. Sanitize inputs // 0. Sanitize inputs notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX); notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX); // Migrate notification flags to scores // Migrate notification flags to scores if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) { if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) { if (notification.priority < Notification.PRIORITY_MAX) notification.priority = Notification.PRIORITY_MAX; if (notification.priority < Notification.PRIORITY_MAX) { } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) { notification.priority = Notification.PRIORITY_MAX; if (notification.priority < Notification.PRIORITY_HIGH) notification.priority = Notification.PRIORITY_HIGH; } } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) { if (notification.priority < Notification.PRIORITY_HIGH) { notification.priority = Notification.PRIORITY_HIGH; } } } // 1. initial score: buckets of 10, around the app // 1. initial score: buckets of 10, around the app Loading @@ -1675,7 +1687,8 @@ public class NotificationManagerService extends INotificationManager.Stub if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) { if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) { if (!isSystemNotification) { if (!isSystemNotification) { score = JUNK_SCORE; score = JUNK_SCORE; Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); } } } } Loading Loading @@ -1769,7 +1782,8 @@ public class NotificationManagerService extends INotificationManager.Stub } } // ATTENTION: in a future release we will bail out here // ATTENTION: in a future release we will bail out here // so that we do not play sounds, show lights, etc. for invalid notifications // so that we do not play sounds, show lights, etc. for invalid notifications Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName()); Slog.e(TAG, "WARNING: In a future release this will crash the app: " + n.getPackageName()); } } // If we're not supposed to beep, vibrate, etc. then don't. // If we're not supposed to beep, vibrate, etc. then don't. Loading @@ -1786,11 +1800,13 @@ public class NotificationManagerService extends INotificationManager.Stub // sound // sound // should we use the default notification sound? (indicated either by DEFAULT_SOUND // should we use the default notification sound? (indicated either by // or because notification.sound is pointing at Settings.System.NOTIFICATION_SOUND) // DEFAULT_SOUND or because notification.sound is pointing at // Settings.System.NOTIFICATION_SOUND) final boolean useDefaultSound = final boolean useDefaultSound = (notification.defaults & Notification.DEFAULT_SOUND) != 0 (notification.defaults & Notification.DEFAULT_SOUND) != 0 || || Settings.System.DEFAULT_NOTIFICATION_URI.equals(notification.sound); Settings.System.DEFAULT_NOTIFICATION_URI .equals(notification.sound); Uri soundUri = null; Uri soundUri = null; boolean hasValidSound = false; boolean hasValidSound = false; Loading @@ -1816,8 +1832,8 @@ public class NotificationManagerService extends INotificationManager.Stub audioStreamType = DEFAULT_STREAM_TYPE; audioStreamType = DEFAULT_STREAM_TYPE; } } mSoundNotification = r; mSoundNotification = r; // do not play notifications if stream volume is 0 // do not play notifications if stream volume is 0 (typically because // (typically because ringer mode is silent) or if speech recognition is active. // ringer mode is silent) or if speech recognition is active. if ((audioManager.getStreamVolume(audioStreamType) != 0) if ((audioManager.getStreamVolume(audioStreamType) != 0) && !audioManager.isSpeechRecognitionActive()) { && !audioManager.isSpeechRecognitionActive()) { final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading @@ -1837,37 +1853,43 @@ public class NotificationManagerService extends INotificationManager.Stub // Does the notification want to specify its own vibration? // Does the notification want to specify its own vibration? final boolean hasCustomVibrate = notification.vibrate != null; final boolean hasCustomVibrate = notification.vibrate != null; // new in 4.2: if there was supposed to be a sound and we're in vibrate mode, // new in 4.2: if there was supposed to be a sound and we're in vibrate // and no other vibration is specified, we fall back to vibration // mode, and no other vibration is specified, we fall back to vibration final boolean convertSoundToVibration = final boolean convertSoundToVibration = !hasCustomVibrate !hasCustomVibrate && hasValidSound && hasValidSound && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE); && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE); // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. final boolean useDefaultVibrate = final boolean useDefaultVibrate = (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; mVibrateNotification = r; if (useDefaultVibrate || convertSoundToVibration) { if (useDefaultVibrate || convertSoundToVibration) { // Escalate privileges so we can use the vibrator even if the notifying app // Escalate privileges so we can use the vibrator even if the // does not have the VIBRATE permission. // notifying app does not have the VIBRATE permission. long identity = Binder.clearCallingIdentity(); long identity = Binder.clearCallingIdentity(); try { try { mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), useDefaultVibrate ? mDefaultVibrationPattern useDefaultVibrate ? mDefaultVibrationPattern : mFallbackVibrationPattern, : mFallbackVibrationPattern, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); } finally { } finally { Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity); } } } else if (notification.vibrate.length > 1) { } else if (notification.vibrate.length > 1) { // If you want your own vibration pattern, you need the VIBRATE permission // If you want your own vibration pattern, you need the VIBRATE mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, // permission ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); } } } } } } Loading @@ -1879,7 +1901,8 @@ public class NotificationManagerService extends INotificationManager.Stub mLedNotification = null; mLedNotification = null; } } //Slog.i(TAG, "notification.lights=" //Slog.i(TAG, "notification.lights=" // + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) != 0)); // + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) // != 0)); if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && canInterrupt) { && canInterrupt) { mLights.add(r); mLights.add(r); Loading @@ -1891,6 +1914,8 @@ public class NotificationManagerService extends INotificationManager.Stub } } } } } } } }); idOut[0] = id; idOut[0] = id; } } Loading