Loading services/java/com/android/server/NotificationManagerService.java +161 −133 Original line number Diff line number Diff line Loading @@ -98,10 +98,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.Calendar; import java.util.Map; import libcore.io.IoUtils; Loading Loading @@ -156,6 +155,7 @@ public class NotificationManagerService extends INotificationManager.Stub private long[] mDefaultVibrationPattern; private long[] mFallbackVibrationPattern; private long[] mNoAlertsVibrationPattern; private boolean mSystemReady; private int mDisabledNotifications; Loading Loading @@ -183,6 +183,18 @@ public class NotificationManagerService extends INotificationManager.Stub private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>(); private NotificationRecord mLedNotification; private boolean mQuietHoursEnabled = false; // Minutes from midnight when quiet hours begin. private int mQuietHoursStart = 0; // Minutes from midnight when quiet hours end. private int mQuietHoursEnd = 0; // Don't play sounds. private boolean mQuietHoursMute = true; // Don't vibrate. private boolean mQuietHoursStill = true; // Dim LED if hardware supports it. private boolean mQuietHoursDim = true; private final AppOpsManager mAppOps; // contains connections to all connected listeners, including app services Loading @@ -198,18 +210,6 @@ public class NotificationManagerService extends INotificationManager.Stub // Just the packages from mEnabledListenersForCurrentUser private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>(); private boolean mQuietHoursEnabled = false; // Minutes from midnight when quiet hours begin. private int mQuietHoursStart = 0; // Minutes from midnight when quiet hours end. private int mQuietHoursEnd = 0; // Don't play sounds. private boolean mQuietHoursMute = true; // Don't vibrate. private boolean mQuietHoursStill = true; // Dim LED if hardware supports it. private boolean mQuietHoursDim = true; // Notification control database. For now just contains disabled packages. private AtomicFile mPolicyFile; private HashSet<String> mBlockedPackages = new HashSet<String>(); Loading Loading @@ -1273,7 +1273,6 @@ public class NotificationManagerService extends INotificationManager.Stub class LEDSettingsObserver extends ContentObserver { private final Uri NOTIFICATION_LIGHT_PULSE_URI = Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE); private final Uri ENABLED_NOTIFICATION_LISTENERS_URI = Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); Loading @@ -1283,33 +1282,29 @@ public class NotificationManagerService extends INotificationManager.Stub void observe() { ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE), false, this); resolver.registerContentObserver( NOTIFICATION_LIGHT_PULSE_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver( ENABLED_NOTIFICATION_LISTENERS_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES), false, this, UserHandle.USER_ALL); update(null); } @Override public void onChange(boolean selfChange, Uri uri) { update(uri); updateNotificationPulse(); } public void update(Uri uri) { ContentResolver resolver = mContext.getContentResolver(); if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) { // LED enabled mNotificationPulseEnabled = Settings.System.getIntForUser(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0; Loading Loading @@ -1337,10 +1332,6 @@ public class NotificationManagerService extends INotificationManager.Stub parseNotificationPulseCustomValuesString(Settings.System.getStringForUser(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES, UserHandle.USER_CURRENT)); } } if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) { rebindListenerServices(); } if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) { rebindListenerServices(); Loading @@ -1348,21 +1339,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } private LEDSettingsObserver mSettingsObserver; static long[] getLongArray(Resources r, int resid, int maxlen, long[] def) { int[] ar = r.getIntArray(resid); if (ar == null) { return def; } final int len = ar.length > maxlen ? maxlen : ar.length; long[] out = new long[len]; for (int i=0; i<len; i++) { out[i] = ar[i]; } return out; } class QuietHoursSettingsObserver extends ContentObserver { QuietHoursSettingsObserver(Handler handler) { super(handler); Loading Loading @@ -1407,6 +1383,21 @@ public class NotificationManagerService extends INotificationManager.Stub } } private LEDSettingsObserver mSettingsObserver; static long[] getLongArray(Resources r, int resid, int maxlen, long[] def) { int[] ar = r.getIntArray(resid); if (ar == null) { return def; } final int len = ar.length > maxlen ? maxlen : ar.length; long[] out = new long[len]; for (int i=0; i<len; i++) { out[i] = ar[i]; } return out; } NotificationManagerService(Context context, StatusBarManagerService statusBar, LightsService lights) { Loading Loading @@ -1436,6 +1427,15 @@ public class NotificationManagerService extends INotificationManager.Stub mDefaultNotificationLedOff = resources.getInteger( R.integer.config_defaultNotificationLedOff); mNotificationPulseCustomLedValues = new HashMap<String, NotificationLedValues>(); mPackageNameMappings = new HashMap<String, String>(); for(String mapping : resources.getStringArray( com.android.internal.R.array.notification_light_package_mapping)) { String[] map = mapping.split("\\|"); mPackageNameMappings.put(map[0], map[1]); } mDefaultVibrationPattern = getLongArray(resources, R.array.config_defaultNotificationVibePattern, VIBRATE_PATTERN_MAXLEN, Loading @@ -1446,14 +1446,10 @@ public class NotificationManagerService extends INotificationManager.Stub VIBRATE_PATTERN_MAXLEN, DEFAULT_VIBRATE_PATTERN); mNotificationPulseCustomLedValues = new HashMap<String, NotificationLedValues>(); mPackageNameMappings = new HashMap<String, String>(); for(String mapping : resources.getStringArray( com.android.internal.R.array.notification_light_package_mapping)) { String[] map = mapping.split("\\|"); mPackageNameMappings.put(map[0], map[1]); } mNoAlertsVibrationPattern = getLongArray(resources, com.android.internal.R.array.config_notificationNoAlertsVibePattern, VIBRATE_PATTERN_MAXLEN, DEFAULT_VIBRATE_PATTERN); // Don't start allowing notifications until the setup wizard has run once. // After that, including subsequent boots, init with notifications turned on. Loading @@ -1471,9 +1467,9 @@ public class NotificationManagerService extends INotificationManager.Stub filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); filter.addAction(Intent.ACTION_USER_PRESENT); filter.addAction(Intent.ACTION_USER_STOPPED); filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_DREAMING_STARTED); filter.addAction(Intent.ACTION_DREAMING_STOPPED); filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mIntentReceiver, filter); IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); Loading @@ -1486,10 +1482,10 @@ public class NotificationManagerService extends INotificationManager.Stub IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mContext.registerReceiver(mIntentReceiver, sdFilter); LEDSettingsObserver ledObserver = new LEDSettingsObserver(mHandler); ledObserver.observe(); QuietHoursSettingsObserver qhObserver = new QuietHoursSettingsObserver(mHandler); qhObserver.observe(); mSettingsObserver = new LEDSettingsObserver(mHandler); mSettingsObserver.observe(); // spin up NotificationScorers String[] notificationScorerNames = resources.getStringArray( Loading Loading @@ -1885,6 +1881,7 @@ public class NotificationManagerService extends INotificationManager.Stub synchronized (mNotificationList) { final boolean inQuietHours = inQuietHours(); final StatusBarNotification n = new StatusBarNotification( pkg, id, tag, callingUid, callingPid, score, notification, user); NotificationRecord r = new NotificationRecord(n); Loading Loading @@ -1978,15 +1975,15 @@ public class NotificationManagerService extends INotificationManager.Stub Log.e(TAG, "An error occurred profiling the notification.", th); } // If we're not supposed to beep, vibrate, etc. then don't. if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) && (!(old != null && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) && (r.getUserId() == UserHandle.USER_ALL || (r.getUserId() == userId && r.getUserId() == currentUser)) && canInterrupt && mSystemReady) { final boolean alertsDisabled = (mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; boolean readyForAlerts = canInterrupt && mSystemReady && (r.getUserId() == UserHandle.USER_ALL || r.getUserId() == userId && r.getUserId() == currentUser) && (old == null || (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0); boolean hasValidSound = false; // If we're not supposed to beep, vibrate, etc. then don't. if (readyForAlerts && !alertsDisabled) { final AudioManager audioManager = (AudioManager) mContext .getSystemService(Context.AUDIO_SERVICE); Loading @@ -2001,9 +1998,7 @@ public class NotificationManagerService extends INotificationManager.Stub .equals(notification.sound); Uri soundUri = null; boolean hasValidSound = false; if (!(inQuietHours && mQuietHoursStill) && useDefaultSound) { if (!(inQuietHours && mQuietHoursMute) && useDefaultSound) { soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; // check to see if the default notification sound is silent Loading Loading @@ -2040,8 +2035,12 @@ public class NotificationManagerService extends INotificationManager.Stub } } } } if (readyForAlerts && (!alertsDisabled || canVibrateDuringAlertsDisabled())) { // vibrate final AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); // Does the notification want to specify its own vibration? final boolean hasCustomVibrate = notification.vibrate != null; Loading @@ -2050,39 +2049,46 @@ public class NotificationManagerService extends INotificationManager.Stub final boolean convertSoundToVibration = !hasCustomVibrate && hasValidSound && shouldConvertSoundToVibration() && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) && (Settings.System.getInt(mContext.getContentResolver(), Settings.System.NOTIFICATION_CONVERT_SOUND_TO_VIBRATION, 1) != 0); == AudioManager.RINGER_MODE_VIBRATE); // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. final boolean useDefaultVibrate = (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; if (!(inQuietHours && mQuietHoursStill) && (useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) if (!(inQuietHours && mQuietHoursStill) && (useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; int repeat = (notification.flags & Notification.FLAG_INSISTENT) != 0 ? 0: -1; long[] pattern; if (alertsDisabled) { pattern = mNoAlertsVibrationPattern; } else if (useDefaultVibrate) { pattern = mDefaultVibrationPattern; } else if (hasCustomVibrate) { pattern = notification.vibrate; } else { pattern = mFallbackVibrationPattern; } if (useDefaultVibrate || convertSoundToVibration) { // Escalate privileges so we can use the vibrator even if the // notifying app does not have the VIBRATE permission. long identity = Binder.clearCallingIdentity(); try { mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), useDefaultVibrate ? mDefaultVibrationPattern : mFallbackVibrationPattern, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), pattern, repeat); } finally { Binder.restoreCallingIdentity(identity); } } else if (notification.vibrate.length > 1) { } else if (pattern.length > 1) { // If you want your own vibration pattern, you need the VIBRATE // permission mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, repeat); } } } Loading Loading @@ -2115,6 +2121,18 @@ public class NotificationManagerService extends INotificationManager.Stub idOut[0] = id; } private boolean shouldConvertSoundToVibration() { return Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.NOTIFICATION_CONVERT_SOUND_TO_VIBRATION, 1, UserHandle.USER_CURRENT_OR_SELF) != 0; } private boolean canVibrateDuringAlertsDisabled() { return Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.NOTIFICATION_VIBRATE_DURING_ALERTS_DISABLED, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; } private boolean inQuietHours() { if (mQuietHoursEnabled && (mQuietHoursStart != mQuietHoursEnd)) { // Get the date in "quiet hours" format. Loading Loading @@ -2311,7 +2329,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) { checkCallerIsSystemOrSameApp(pkg); checkCallerCanCancelNotification(pkg); userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg); // Don't allow client applications to cancel foreground service notis. Loading @@ -2321,7 +2339,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelAllNotifications(String pkg, int userId) { checkCallerIsSystemOrSameApp(pkg); checkCallerCanCancelNotification(pkg); userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg); Loading Loading @@ -2350,6 +2368,14 @@ public class NotificationManagerService extends INotificationManager.Stub throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid()); } void checkCallerCanCancelNotification(String pkg) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.CANCEL_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) { return; } checkCallerIsSystemOrSameApp(pkg); } void checkCallerIsSystemOrSameApp(String pkg) { if (isCallerSystem()) { return; Loading Loading @@ -2389,51 +2415,50 @@ public class NotificationManagerService extends INotificationManager.Stub } // lock on mNotificationList private void updateLightsLocked() { private void updateLightsLocked() { // handle notification lights if (mLedNotification == null) { // use most recent light with highest score for (int i = mLights.size(); i > 0; i--) { NotificationRecord r = mLights.get(i - 1); if (mLedNotification == null || r.score > mLedNotification.score) { if (mLedNotification == null || r.sbn.getScore() > mLedNotification.sbn.getScore()) { mLedNotification = r; } } } // Don't flash while we are in a call, screen is on or we are in quiet hours with light dimmed // Don't flash while we are in a call, screen is on or we are // in quiet hours with light dimmed if (mLedNotification == null || mInCall || (mScreenOn && !mDreaming) || (inQuietHours() && mQuietHoursDim)) { mNotificationLight.turnOff(); } else { } else if (mNotificationPulseEnabled) { final Notification ledno = mLedNotification.sbn.getNotification(); final NotificationLedValues ledValues = getLedValuesForNotification(mLedNotification); int ledARGB; int ledOnMS; int ledOffMS; NotificationLedValues ledValues = getLedValuesForNotification(mLedNotification); if (ledValues != null) { ledARGB = ledValues.color != 0 ? ledValues.color : mDefaultNotificationColor; ledOnMS = ledValues.onMS >= 0 ? ledValues.onMS : mDefaultNotificationLedOn; ledOffMS = ledValues.offMS >= 0 ? ledValues.offMS : mDefaultNotificationLedOff; } else { if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) { } else if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) { ledARGB = mDefaultNotificationColor; ledOnMS = mDefaultNotificationLedOn; ledOffMS = mDefaultNotificationLedOff; } else { ledARGB = mLedNotification.notification.ledARGB; ledOnMS = mLedNotification.notification.ledOnMS; ledOffMS = mLedNotification.notification.ledOffMS; ledARGB = ledno.ledARGB; ledOnMS = ledno.ledOnMS; ledOffMS = ledno.ledOffMS; } } if (mNotificationPulseEnabled) { // pulse repeatedly mNotificationLight.setFlashing(ledARGB, LightsService.LIGHT_FLASH_TIMED, ledOnMS, ledOffMS); } } } private void parseNotificationPulseCustomValuesString(String customLedValuesString) { if (TextUtils.isEmpty(customLedValuesString)) { Loading @@ -2449,7 +2474,8 @@ public class NotificationManagerService extends INotificationManager.Stub String packageName = packageValues[0]; String[] values = packageValues[1].split(";"); if (values.length != 3) { Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); continue; } NotificationLedValues ledValues = new NotificationLedValues(); Loading @@ -2458,7 +2484,8 @@ public class NotificationManagerService extends INotificationManager.Stub ledValues.onMS = Integer.parseInt(values[1]); ledValues.offMS = Integer.parseInt(values[2]); } catch (Exception e) { Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); continue; } mNotificationPulseCustomLedValues.put(packageName, ledValues); Loading @@ -2466,7 +2493,8 @@ public class NotificationManagerService extends INotificationManager.Stub } private NotificationLedValues getLedValuesForNotification(NotificationRecord ledNotification) { return mNotificationPulseCustomLedValues.get(mapPackage(ledNotification.pkg)); final String packageName = ledNotification.sbn.getPackageName(); return mNotificationPulseCustomLedValues.get(mapPackage(packageName)); } private String mapPackage(String pkg) { Loading Loading
services/java/com/android/server/NotificationManagerService.java +161 −133 Original line number Diff line number Diff line Loading @@ -98,10 +98,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.Calendar; import java.util.Map; import libcore.io.IoUtils; Loading Loading @@ -156,6 +155,7 @@ public class NotificationManagerService extends INotificationManager.Stub private long[] mDefaultVibrationPattern; private long[] mFallbackVibrationPattern; private long[] mNoAlertsVibrationPattern; private boolean mSystemReady; private int mDisabledNotifications; Loading Loading @@ -183,6 +183,18 @@ public class NotificationManagerService extends INotificationManager.Stub private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>(); private NotificationRecord mLedNotification; private boolean mQuietHoursEnabled = false; // Minutes from midnight when quiet hours begin. private int mQuietHoursStart = 0; // Minutes from midnight when quiet hours end. private int mQuietHoursEnd = 0; // Don't play sounds. private boolean mQuietHoursMute = true; // Don't vibrate. private boolean mQuietHoursStill = true; // Dim LED if hardware supports it. private boolean mQuietHoursDim = true; private final AppOpsManager mAppOps; // contains connections to all connected listeners, including app services Loading @@ -198,18 +210,6 @@ public class NotificationManagerService extends INotificationManager.Stub // Just the packages from mEnabledListenersForCurrentUser private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>(); private boolean mQuietHoursEnabled = false; // Minutes from midnight when quiet hours begin. private int mQuietHoursStart = 0; // Minutes from midnight when quiet hours end. private int mQuietHoursEnd = 0; // Don't play sounds. private boolean mQuietHoursMute = true; // Don't vibrate. private boolean mQuietHoursStill = true; // Dim LED if hardware supports it. private boolean mQuietHoursDim = true; // Notification control database. For now just contains disabled packages. private AtomicFile mPolicyFile; private HashSet<String> mBlockedPackages = new HashSet<String>(); Loading Loading @@ -1273,7 +1273,6 @@ public class NotificationManagerService extends INotificationManager.Stub class LEDSettingsObserver extends ContentObserver { private final Uri NOTIFICATION_LIGHT_PULSE_URI = Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE); private final Uri ENABLED_NOTIFICATION_LISTENERS_URI = Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); Loading @@ -1283,33 +1282,29 @@ public class NotificationManagerService extends INotificationManager.Stub void observe() { ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE), false, this); resolver.registerContentObserver( NOTIFICATION_LIGHT_PULSE_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver( ENABLED_NOTIFICATION_LISTENERS_URI, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES), false, this); Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES), false, this, UserHandle.USER_ALL); update(null); } @Override public void onChange(boolean selfChange, Uri uri) { update(uri); updateNotificationPulse(); } public void update(Uri uri) { ContentResolver resolver = mContext.getContentResolver(); if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) { // LED enabled mNotificationPulseEnabled = Settings.System.getIntForUser(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0; Loading Loading @@ -1337,10 +1332,6 @@ public class NotificationManagerService extends INotificationManager.Stub parseNotificationPulseCustomValuesString(Settings.System.getStringForUser(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES, UserHandle.USER_CURRENT)); } } if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) { rebindListenerServices(); } if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) { rebindListenerServices(); Loading @@ -1348,21 +1339,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } private LEDSettingsObserver mSettingsObserver; static long[] getLongArray(Resources r, int resid, int maxlen, long[] def) { int[] ar = r.getIntArray(resid); if (ar == null) { return def; } final int len = ar.length > maxlen ? maxlen : ar.length; long[] out = new long[len]; for (int i=0; i<len; i++) { out[i] = ar[i]; } return out; } class QuietHoursSettingsObserver extends ContentObserver { QuietHoursSettingsObserver(Handler handler) { super(handler); Loading Loading @@ -1407,6 +1383,21 @@ public class NotificationManagerService extends INotificationManager.Stub } } private LEDSettingsObserver mSettingsObserver; static long[] getLongArray(Resources r, int resid, int maxlen, long[] def) { int[] ar = r.getIntArray(resid); if (ar == null) { return def; } final int len = ar.length > maxlen ? maxlen : ar.length; long[] out = new long[len]; for (int i=0; i<len; i++) { out[i] = ar[i]; } return out; } NotificationManagerService(Context context, StatusBarManagerService statusBar, LightsService lights) { Loading Loading @@ -1436,6 +1427,15 @@ public class NotificationManagerService extends INotificationManager.Stub mDefaultNotificationLedOff = resources.getInteger( R.integer.config_defaultNotificationLedOff); mNotificationPulseCustomLedValues = new HashMap<String, NotificationLedValues>(); mPackageNameMappings = new HashMap<String, String>(); for(String mapping : resources.getStringArray( com.android.internal.R.array.notification_light_package_mapping)) { String[] map = mapping.split("\\|"); mPackageNameMappings.put(map[0], map[1]); } mDefaultVibrationPattern = getLongArray(resources, R.array.config_defaultNotificationVibePattern, VIBRATE_PATTERN_MAXLEN, Loading @@ -1446,14 +1446,10 @@ public class NotificationManagerService extends INotificationManager.Stub VIBRATE_PATTERN_MAXLEN, DEFAULT_VIBRATE_PATTERN); mNotificationPulseCustomLedValues = new HashMap<String, NotificationLedValues>(); mPackageNameMappings = new HashMap<String, String>(); for(String mapping : resources.getStringArray( com.android.internal.R.array.notification_light_package_mapping)) { String[] map = mapping.split("\\|"); mPackageNameMappings.put(map[0], map[1]); } mNoAlertsVibrationPattern = getLongArray(resources, com.android.internal.R.array.config_notificationNoAlertsVibePattern, VIBRATE_PATTERN_MAXLEN, DEFAULT_VIBRATE_PATTERN); // Don't start allowing notifications until the setup wizard has run once. // After that, including subsequent boots, init with notifications turned on. Loading @@ -1471,9 +1467,9 @@ public class NotificationManagerService extends INotificationManager.Stub filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); filter.addAction(Intent.ACTION_USER_PRESENT); filter.addAction(Intent.ACTION_USER_STOPPED); filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_DREAMING_STARTED); filter.addAction(Intent.ACTION_DREAMING_STOPPED); filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mIntentReceiver, filter); IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); Loading @@ -1486,10 +1482,10 @@ public class NotificationManagerService extends INotificationManager.Stub IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mContext.registerReceiver(mIntentReceiver, sdFilter); LEDSettingsObserver ledObserver = new LEDSettingsObserver(mHandler); ledObserver.observe(); QuietHoursSettingsObserver qhObserver = new QuietHoursSettingsObserver(mHandler); qhObserver.observe(); mSettingsObserver = new LEDSettingsObserver(mHandler); mSettingsObserver.observe(); // spin up NotificationScorers String[] notificationScorerNames = resources.getStringArray( Loading Loading @@ -1885,6 +1881,7 @@ public class NotificationManagerService extends INotificationManager.Stub synchronized (mNotificationList) { final boolean inQuietHours = inQuietHours(); final StatusBarNotification n = new StatusBarNotification( pkg, id, tag, callingUid, callingPid, score, notification, user); NotificationRecord r = new NotificationRecord(n); Loading Loading @@ -1978,15 +1975,15 @@ public class NotificationManagerService extends INotificationManager.Stub Log.e(TAG, "An error occurred profiling the notification.", th); } // If we're not supposed to beep, vibrate, etc. then don't. if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) && (!(old != null && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) && (r.getUserId() == UserHandle.USER_ALL || (r.getUserId() == userId && r.getUserId() == currentUser)) && canInterrupt && mSystemReady) { final boolean alertsDisabled = (mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; boolean readyForAlerts = canInterrupt && mSystemReady && (r.getUserId() == UserHandle.USER_ALL || r.getUserId() == userId && r.getUserId() == currentUser) && (old == null || (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0); boolean hasValidSound = false; // If we're not supposed to beep, vibrate, etc. then don't. if (readyForAlerts && !alertsDisabled) { final AudioManager audioManager = (AudioManager) mContext .getSystemService(Context.AUDIO_SERVICE); Loading @@ -2001,9 +1998,7 @@ public class NotificationManagerService extends INotificationManager.Stub .equals(notification.sound); Uri soundUri = null; boolean hasValidSound = false; if (!(inQuietHours && mQuietHoursStill) && useDefaultSound) { if (!(inQuietHours && mQuietHoursMute) && useDefaultSound) { soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; // check to see if the default notification sound is silent Loading Loading @@ -2040,8 +2035,12 @@ public class NotificationManagerService extends INotificationManager.Stub } } } } if (readyForAlerts && (!alertsDisabled || canVibrateDuringAlertsDisabled())) { // vibrate final AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); // Does the notification want to specify its own vibration? final boolean hasCustomVibrate = notification.vibrate != null; Loading @@ -2050,39 +2049,46 @@ public class NotificationManagerService extends INotificationManager.Stub final boolean convertSoundToVibration = !hasCustomVibrate && hasValidSound && shouldConvertSoundToVibration() && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) && (Settings.System.getInt(mContext.getContentResolver(), Settings.System.NOTIFICATION_CONVERT_SOUND_TO_VIBRATION, 1) != 0); == AudioManager.RINGER_MODE_VIBRATE); // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback. final boolean useDefaultVibrate = (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; if (!(inQuietHours && mQuietHoursStill) && (useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) if (!(inQuietHours && mQuietHoursStill) && (useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; int repeat = (notification.flags & Notification.FLAG_INSISTENT) != 0 ? 0: -1; long[] pattern; if (alertsDisabled) { pattern = mNoAlertsVibrationPattern; } else if (useDefaultVibrate) { pattern = mDefaultVibrationPattern; } else if (hasCustomVibrate) { pattern = notification.vibrate; } else { pattern = mFallbackVibrationPattern; } if (useDefaultVibrate || convertSoundToVibration) { // Escalate privileges so we can use the vibrator even if the // notifying app does not have the VIBRATE permission. long identity = Binder.clearCallingIdentity(); try { mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), useDefaultVibrate ? mDefaultVibrationPattern : mFallbackVibrationPattern, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), pattern, repeat); } finally { Binder.restoreCallingIdentity(identity); } } else if (notification.vibrate.length > 1) { } else if (pattern.length > 1) { // If you want your own vibration pattern, you need the VIBRATE // permission mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1); mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(), notification.vibrate, repeat); } } } Loading Loading @@ -2115,6 +2121,18 @@ public class NotificationManagerService extends INotificationManager.Stub idOut[0] = id; } private boolean shouldConvertSoundToVibration() { return Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.NOTIFICATION_CONVERT_SOUND_TO_VIBRATION, 1, UserHandle.USER_CURRENT_OR_SELF) != 0; } private boolean canVibrateDuringAlertsDisabled() { return Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.NOTIFICATION_VIBRATE_DURING_ALERTS_DISABLED, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; } private boolean inQuietHours() { if (mQuietHoursEnabled && (mQuietHoursStart != mQuietHoursEnd)) { // Get the date in "quiet hours" format. Loading Loading @@ -2311,7 +2329,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) { checkCallerIsSystemOrSameApp(pkg); checkCallerCanCancelNotification(pkg); userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg); // Don't allow client applications to cancel foreground service notis. Loading @@ -2321,7 +2339,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelAllNotifications(String pkg, int userId) { checkCallerIsSystemOrSameApp(pkg); checkCallerCanCancelNotification(pkg); userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true, false, "cancelAllNotifications", pkg); Loading Loading @@ -2350,6 +2368,14 @@ public class NotificationManagerService extends INotificationManager.Stub throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid()); } void checkCallerCanCancelNotification(String pkg) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.CANCEL_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) { return; } checkCallerIsSystemOrSameApp(pkg); } void checkCallerIsSystemOrSameApp(String pkg) { if (isCallerSystem()) { return; Loading Loading @@ -2389,51 +2415,50 @@ public class NotificationManagerService extends INotificationManager.Stub } // lock on mNotificationList private void updateLightsLocked() { private void updateLightsLocked() { // handle notification lights if (mLedNotification == null) { // use most recent light with highest score for (int i = mLights.size(); i > 0; i--) { NotificationRecord r = mLights.get(i - 1); if (mLedNotification == null || r.score > mLedNotification.score) { if (mLedNotification == null || r.sbn.getScore() > mLedNotification.sbn.getScore()) { mLedNotification = r; } } } // Don't flash while we are in a call, screen is on or we are in quiet hours with light dimmed // Don't flash while we are in a call, screen is on or we are // in quiet hours with light dimmed if (mLedNotification == null || mInCall || (mScreenOn && !mDreaming) || (inQuietHours() && mQuietHoursDim)) { mNotificationLight.turnOff(); } else { } else if (mNotificationPulseEnabled) { final Notification ledno = mLedNotification.sbn.getNotification(); final NotificationLedValues ledValues = getLedValuesForNotification(mLedNotification); int ledARGB; int ledOnMS; int ledOffMS; NotificationLedValues ledValues = getLedValuesForNotification(mLedNotification); if (ledValues != null) { ledARGB = ledValues.color != 0 ? ledValues.color : mDefaultNotificationColor; ledOnMS = ledValues.onMS >= 0 ? ledValues.onMS : mDefaultNotificationLedOn; ledOffMS = ledValues.offMS >= 0 ? ledValues.offMS : mDefaultNotificationLedOff; } else { if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) { } else if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) { ledARGB = mDefaultNotificationColor; ledOnMS = mDefaultNotificationLedOn; ledOffMS = mDefaultNotificationLedOff; } else { ledARGB = mLedNotification.notification.ledARGB; ledOnMS = mLedNotification.notification.ledOnMS; ledOffMS = mLedNotification.notification.ledOffMS; ledARGB = ledno.ledARGB; ledOnMS = ledno.ledOnMS; ledOffMS = ledno.ledOffMS; } } if (mNotificationPulseEnabled) { // pulse repeatedly mNotificationLight.setFlashing(ledARGB, LightsService.LIGHT_FLASH_TIMED, ledOnMS, ledOffMS); } } } private void parseNotificationPulseCustomValuesString(String customLedValuesString) { if (TextUtils.isEmpty(customLedValuesString)) { Loading @@ -2449,7 +2474,8 @@ public class NotificationManagerService extends INotificationManager.Stub String packageName = packageValues[0]; String[] values = packageValues[1].split(";"); if (values.length != 3) { Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); continue; } NotificationLedValues ledValues = new NotificationLedValues(); Loading @@ -2458,7 +2484,8 @@ public class NotificationManagerService extends INotificationManager.Stub ledValues.onMS = Integer.parseInt(values[1]); ledValues.offMS = Integer.parseInt(values[2]); } catch (Exception e) { Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); Log.e(TAG, "Error parsing custom led values '" + packageValues[1] + "' for " + packageName); continue; } mNotificationPulseCustomLedValues.put(packageName, ledValues); Loading @@ -2466,7 +2493,8 @@ public class NotificationManagerService extends INotificationManager.Stub } private NotificationLedValues getLedValuesForNotification(NotificationRecord ledNotification) { return mNotificationPulseCustomLedValues.get(mapPackage(ledNotification.pkg)); final String packageName = ledNotification.sbn.getPackageName(); return mNotificationPulseCustomLedValues.get(mapPackage(packageName)); } private String mapPackage(String pkg) { Loading