@@ -101,6 +101,7 @@ public class NotificationManagerService extends INotificationManager.Stub
101101 private static final int SHORT_DELAY = 2000 ; // 2 seconds
102102
103103 private static final long [] DEFAULT_VIBRATE_PATTERN = {0 , 250 , 250 , 250 };
104+ private static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1 ; // up to eight bumps
104105
105106 private static final int DEFAULT_STREAM_TYPE = AudioManager .STREAM_NOTIFICATION ;
106107 private static final boolean SCORE_ONGOING_HIGHER = false ;
@@ -125,6 +126,9 @@ public class NotificationManagerService extends INotificationManager.Stub
125126 private int mDefaultNotificationLedOn ;
126127 private int mDefaultNotificationLedOff ;
127128
129+ private long [] mDefaultVibrationPattern ;
130+ private long [] mFallbackVibrationPattern ;
131+
128132 private boolean mSystemReady ;
129133 private int mDisabledNotifications ;
130134
@@ -596,6 +600,19 @@ public void update() {
596600 }
597601 }
598602
603+ static long [] getLongArray (Resources r , int resid , int maxlen , long [] def ) {
604+ int [] ar = r .getIntArray (resid );
605+ if (ar == null ) {
606+ return def ;
607+ }
608+ final int len = ar .length > maxlen ? maxlen : ar .length ;
609+ long [] out = new long [len ];
610+ for (int i =0 ; i <len ; i ++) {
611+ out [i ] = ar [i ];
612+ }
613+ return out ;
614+ }
615+
599616 NotificationManagerService (Context context , StatusBarManagerService statusBar ,
600617 LightsService lights )
601618 {
@@ -622,6 +639,16 @@ public void update() {
622639 mDefaultNotificationLedOff = resources .getInteger (
623640 com .android .internal .R .integer .config_defaultNotificationLedOff );
624641
642+ mDefaultVibrationPattern = getLongArray (resources ,
643+ com .android .internal .R .array .config_defaultNotificationVibePattern ,
644+ VIBRATE_PATTERN_MAXLEN ,
645+ DEFAULT_VIBRATE_PATTERN );
646+
647+ mFallbackVibrationPattern = getLongArray (resources ,
648+ com .android .internal .R .array .config_notificationFallbackVibePattern ,
649+ VIBRATE_PATTERN_MAXLEN ,
650+ DEFAULT_VIBRATE_PATTERN );
651+
625652 // Don't start allowing notifications until the setup wizard has run once.
626653 // After that, including subsequent boots, init with notifications turned on.
627654 // This works on the first boot because the setup wizard will toggle this
@@ -1086,24 +1113,40 @@ public void enqueueNotificationInternal(String pkg, int callingUid, int callingP
10861113 }
10871114
10881115 // vibrate
1116+ // Does the notification want to specify its own vibration?
1117+ final boolean hasCustomVibrate = notification .vibrate != null ;
1118+
10891119 // new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
1090- // we always vibrate, even if no vibration was specified
1120+ // and no other vibration is specified, we apply the default vibration anyway
10911121 final boolean convertSoundToVibration =
1092- notification . vibrate == null
1122+ ! hasCustomVibrate
10931123 && (useDefaultSound || notification .sound != null )
10941124 && (audioManager .getRingerMode () == AudioManager .RINGER_MODE_VIBRATE );
10951125
1126+ // The DEFAULT_VIBRATE flag trumps any custom vibration.
10961127 final boolean useDefaultVibrate =
1097- (notification .defaults & Notification .DEFAULT_VIBRATE ) != 0
1098- || convertSoundToVibration ;
1128+ (notification .defaults & Notification .DEFAULT_VIBRATE ) != 0 ;
10991129
1100- if ((useDefaultVibrate || notification . vibrate != null )
1130+ if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate )
11011131 && !(audioManager .getRingerMode () == AudioManager .RINGER_MODE_SILENT )) {
11021132 mVibrateNotification = r ;
11031133
1104- mVibrator .vibrate (useDefaultVibrate ? DEFAULT_VIBRATE_PATTERN
1105- : notification .vibrate ,
1106- ((notification .flags & Notification .FLAG_INSISTENT ) != 0 ) ? 0 : -1 );
1134+ if (useDefaultVibrate || convertSoundToVibration ) {
1135+ // Escalate privileges so we can use the vibrator even if the notifying app
1136+ // does not have the VIBRATE permission.
1137+ long identity = Binder .clearCallingIdentity ();
1138+ try {
1139+ mVibrator .vibrate (convertSoundToVibration ? mFallbackVibrationPattern
1140+ : mDefaultVibrationPattern ,
1141+ ((notification .flags & Notification .FLAG_INSISTENT ) != 0 ) ? 0 : -1 );
1142+ } finally {
1143+ Binder .restoreCallingIdentity (identity );
1144+ }
1145+ } else if (notification .vibrate .length > 1 ) {
1146+ // If you want your own vibration pattern, you need the VIBRATE permission
1147+ mVibrator .vibrate (notification .vibrate ,
1148+ ((notification .flags & Notification .FLAG_INSISTENT ) != 0 ) ? 0 : -1 );
1149+ }
11071150 }
11081151 }
11091152
0 commit comments