Notification vibration improvements: [DO NOT MERGE]
- When notifications vibrate as a fallback (that is, because they want to play a sound but the device is in vibrate mode), this no longer requires the VIBRATE permission. - As a bonus, if your notifications use DEFAULT_VIBRATE, you don't need the VIBRATE permission either. - If you specify a custom vibration pattern, you'll still need the VIBRATE permission for that. - Notifications vibrating in fallback mode use same vibration pattern but can be changed easily in future. - The DEFAULT_VIBRATE and fallback vibrate patterns are now specified in config.xml. Bug: 7531442 Change-Id: I7a2d8413d1becc53b9d31f0d1abbc2acc3f650c6
This commit is contained in:
committed by
Dave Burke
parent
721b370c5a
commit
aaec726948
@@ -1000,4 +1000,25 @@
|
|||||||
provisioning on some carriers, working around a bug (7305641)
|
provisioning on some carriers, working around a bug (7305641)
|
||||||
where if the preferred is used we don't try the others. -->
|
where if the preferred is used we don't try the others. -->
|
||||||
<bool name="config_dontPreferApn">false</bool>
|
<bool name="config_dontPreferApn">false</bool>
|
||||||
|
|
||||||
|
<!-- Vibrator pattern to be used as the default for notifications
|
||||||
|
that specify DEFAULT_VIBRATE.
|
||||||
|
-->
|
||||||
|
<integer-array name="config_defaultNotificationVibePattern">
|
||||||
|
<item>0</item>
|
||||||
|
<item>250</item>
|
||||||
|
<item>250</item>
|
||||||
|
<item>250</item>
|
||||||
|
</integer-array>
|
||||||
|
|
||||||
|
<!-- Vibrator pattern to be used as the default for notifications
|
||||||
|
that do not specify vibration but vibrate anyway because the device
|
||||||
|
is in vibrate mode.
|
||||||
|
-->
|
||||||
|
<integer-array name="config_notificationFallbackVibePattern">
|
||||||
|
<item>0</item>
|
||||||
|
<item>250</item>
|
||||||
|
<item>250</item>
|
||||||
|
<item>250</item>
|
||||||
|
</integer-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1525,6 +1525,8 @@
|
|||||||
<java-symbol type="array" name="radioAttributes" />
|
<java-symbol type="array" name="radioAttributes" />
|
||||||
<java-symbol type="array" name="config_oemUsbModeOverride" />
|
<java-symbol type="array" name="config_oemUsbModeOverride" />
|
||||||
<java-symbol type="array" name="config_locationProviderPackageNames" />
|
<java-symbol type="array" name="config_locationProviderPackageNames" />
|
||||||
|
<java-symbol type="array" name="config_defaultNotificationVibePattern" />
|
||||||
|
<java-symbol type="array" name="config_notificationFallbackVibePattern" />
|
||||||
<java-symbol type="bool" name="config_animateScreenLights" />
|
<java-symbol type="bool" name="config_animateScreenLights" />
|
||||||
<java-symbol type="bool" name="config_automatic_brightness_available" />
|
<java-symbol type="bool" name="config_automatic_brightness_available" />
|
||||||
<java-symbol type="bool" name="config_sf_limitedAlpha" />
|
<java-symbol type="bool" name="config_sf_limitedAlpha" />
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
private static final int SHORT_DELAY = 2000; // 2 seconds
|
private static final int SHORT_DELAY = 2000; // 2 seconds
|
||||||
|
|
||||||
private static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};
|
private static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};
|
||||||
|
private static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps
|
||||||
|
|
||||||
private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
|
private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
|
||||||
private static final boolean SCORE_ONGOING_HIGHER = false;
|
private static final boolean SCORE_ONGOING_HIGHER = false;
|
||||||
@@ -125,6 +126,9 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
private int mDefaultNotificationLedOn;
|
private int mDefaultNotificationLedOn;
|
||||||
private int mDefaultNotificationLedOff;
|
private int mDefaultNotificationLedOff;
|
||||||
|
|
||||||
|
private long[] mDefaultVibrationPattern;
|
||||||
|
private long[] mFallbackVibrationPattern;
|
||||||
|
|
||||||
private boolean mSystemReady;
|
private boolean mSystemReady;
|
||||||
private int mDisabledNotifications;
|
private int mDisabledNotifications;
|
||||||
|
|
||||||
@@ -596,6 +600,19 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
NotificationManagerService(Context context, StatusBarManagerService statusBar,
|
||||||
LightsService lights)
|
LightsService lights)
|
||||||
{
|
{
|
||||||
@@ -622,6 +639,16 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
mDefaultNotificationLedOff = resources.getInteger(
|
mDefaultNotificationLedOff = resources.getInteger(
|
||||||
com.android.internal.R.integer.config_defaultNotificationLedOff);
|
com.android.internal.R.integer.config_defaultNotificationLedOff);
|
||||||
|
|
||||||
|
mDefaultVibrationPattern = getLongArray(resources,
|
||||||
|
com.android.internal.R.array.config_defaultNotificationVibePattern,
|
||||||
|
VIBRATE_PATTERN_MAXLEN,
|
||||||
|
DEFAULT_VIBRATE_PATTERN);
|
||||||
|
|
||||||
|
mFallbackVibrationPattern = getLongArray(resources,
|
||||||
|
com.android.internal.R.array.config_notificationFallbackVibePattern,
|
||||||
|
VIBRATE_PATTERN_MAXLEN,
|
||||||
|
DEFAULT_VIBRATE_PATTERN);
|
||||||
|
|
||||||
// Don't start allowing notifications until the setup wizard has run once.
|
// Don't start allowing notifications until the setup wizard has run once.
|
||||||
// After that, including subsequent boots, init with notifications turned on.
|
// After that, including subsequent boots, init with notifications turned on.
|
||||||
// This works on the first boot because the setup wizard will toggle this
|
// This works on the first boot because the setup wizard will toggle this
|
||||||
@@ -1086,24 +1113,40 @@ public class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
// vibrate
|
// vibrate
|
||||||
|
// Does the notification want to specify its own vibration?
|
||||||
|
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 mode,
|
||||||
// we always vibrate, even if no vibration was specified
|
// and no other vibration is specified, we apply the default vibration anyway
|
||||||
final boolean convertSoundToVibration =
|
final boolean convertSoundToVibration =
|
||||||
notification.vibrate == null
|
!hasCustomVibrate
|
||||||
&& (useDefaultSound || notification.sound != null)
|
&& (useDefaultSound || notification.sound != null)
|
||||||
&& (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
|
&& (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
|
||||||
|
|
||||||
|
// The DEFAULT_VIBRATE flag trumps any custom vibration.
|
||||||
final boolean useDefaultVibrate =
|
final boolean useDefaultVibrate =
|
||||||
(notification.defaults & Notification.DEFAULT_VIBRATE) != 0
|
(notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
|
||||||
|| convertSoundToVibration;
|
|
||||||
|
|
||||||
if ((useDefaultVibrate || notification.vibrate != null)
|
if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate)
|
||||||
&& !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) {
|
&& !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) {
|
||||||
mVibrateNotification = r;
|
mVibrateNotification = r;
|
||||||
|
|
||||||
mVibrator.vibrate(useDefaultVibrate ? DEFAULT_VIBRATE_PATTERN
|
if (useDefaultVibrate || convertSoundToVibration) {
|
||||||
: notification.vibrate,
|
// Escalate privileges so we can use the vibrator even if the notifying app
|
||||||
((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
|
// does not have the VIBRATE permission.
|
||||||
|
long identity = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
mVibrator.vibrate(convertSoundToVibration ? mFallbackVibrationPattern
|
||||||
|
: mDefaultVibrationPattern,
|
||||||
|
((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
}
|
||||||
|
} else if (notification.vibrate.length > 1) {
|
||||||
|
// If you want your own vibration pattern, you need the VIBRATE permission
|
||||||
|
mVibrator.vibrate(notification.vibrate,
|
||||||
|
((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user