summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/AlarmManager.java23
-rw-r--r--core/java/android/app/Notification.java13
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java18
-rw-r--r--core/java/android/util/TimeUtils.java86
-rw-r--r--core/tests/notificationtests/src/android/app/NotificationStressTest.java13
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java41
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java4
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java5
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java54
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java20
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java6
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java24
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSpi.java24
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java5
-rw-r--r--keystore/java/android/security/keystore/KeyGenParameterSpec.java15
-rw-r--r--keystore/java/android/security/keystore/KeyProperties.java6
-rw-r--r--keystore/java/android/security/keystore/KeyProtection.java11
-rw-r--r--keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java14
-rw-r--r--keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java7
-rw-r--r--location/java/com/android/internal/location/GpsNetInitiatedHandler.java30
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java157
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java20
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java34
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java29
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java37
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java66
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java49
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java22
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java9
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--tests/ActivityTests/AndroidManifest.xml1
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java28
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java31
-rw-r--r--tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java16
-rw-r--r--tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java21
-rw-r--r--tests/StatusBar/res/drawable-hdpi/stat_sys_warning.pngbin0 -> 769 bytes
-rw-r--r--tests/StatusBar/res/drawable-mdpi/stat_sys_warning.pngbin0 -> 654 bytes
-rw-r--r--tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java550
-rw-r--r--tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java23
39 files changed, 915 insertions, 599 deletions
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 5e7bd0d..9ea1606 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -142,13 +142,22 @@ public class AlarmManager {
public static final int FLAG_ALLOW_WHILE_IDLE = 1<<2;
/**
+ * Flag for alarms: same as {@link #FLAG_ALLOW_WHILE_IDLE}, but doesn't have restrictions
+ * on how frequently it can be scheduled. Only available (and automatically applied) to
+ * system alarms.
+ *
+ * @hide
+ */
+ public static final int FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED = 1<<3;
+
+ /**
* Flag for alarms: this alarm marks the point where we would like to come out of idle
* mode. It may be moved by the alarm manager to match the first wake-from-idle alarm.
* Scheduling an alarm with this flag puts the alarm manager in to idle mode, where it
* avoids scheduling any further alarms until the marker alarm is executed.
* @hide
*/
- public static final int FLAG_IDLE_UNTIL = 1<<3;
+ public static final int FLAG_IDLE_UNTIL = 1<<4;
private final IAlarmManager mService;
private final boolean mAlwaysExact;
@@ -565,6 +574,12 @@ public class AlarmManager {
* of the device when idle (and thus cause significant battery blame to the app scheduling
* them), so they should be used with care.
*
+ * <p>To reduce abuse, there are restrictions on how frequently these alarms will go off
+ * for a particular application. Under normal system operation, it will not dispatch these
+ * alarms more than about every minute (at which point every such pending alarm is
+ * dispatched); when in low-power idle modes this duration may be significantly longer,
+ * such as 15 minutes.</p>
+ *
* <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
* out of order with any other alarms, even those from the same app. This will clearly happen
* when the device is idle (since this alarm can go off while idle, when any other alarms
@@ -608,6 +623,12 @@ public class AlarmManager {
* of the device when idle (and thus cause significant battery blame to the app scheduling
* them), so they should be used with care.
*
+ * <p>To reduce abuse, there are restrictions on how frequently these alarms will go off
+ * for a particular application. Under normal system operation, it will not dispatch these
+ * alarms more than about every minute (at which point every such pending alarm is
+ * dispatched); when in low-power idle modes this duration may be significantly longer,
+ * such as 15 minutes.</p>
+ *
* <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
* out of order with any other alarms, even those from the same app. This will clearly happen
* when the device is idle (since this alarm can go off while idle, when any other alarms
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 96c6878..33a47b2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1331,11 +1331,14 @@ public class Notification implements Parcelable
public Notification(Context context, int icon, CharSequence tickerText, long when,
CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
{
- this.when = when;
- this.icon = icon;
- this.tickerText = tickerText;
- setLatestEventInfo(context, contentTitle, contentText,
- PendingIntent.getActivity(context, 0, contentIntent, 0));
+ new Builder(context)
+ .setWhen(when)
+ .setSmallIcon(icon)
+ .setTicker(tickerText)
+ .setContentTitle(contentTitle)
+ .setContentText(contentText)
+ .setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0))
+ .buildInto(this);
}
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 42d0dcb..9f49154 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -149,6 +149,7 @@ public class DevicePolicyManager {
* <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
* <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
* </ul>
*
* <p> When device owner provisioning has completed, an intent of the type
@@ -163,14 +164,19 @@ public class DevicePolicyManager {
= "android.app.action.PROVISION_MANAGED_DEVICE";
/**
- * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
- * a mobile device management application that starts managed profile provisioning to pass data
- * to itself on the managed profile when provisioning completes. The mobile device management
- * application sends this extra in an intent with the action
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in
+ * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
+ * allows a mobile device management application which starts managed provisioning to pass data
+ * to itself.
+ * <p>
+ * If used with {@link #ACTION_PROVISION_MANAGED_PROFILE} it can be used by the application that
+ * sends the intent to pass data to itself on the newly created profile.
+ * If used with {@link #ACTION_PROVISION_MANAGED_DEVICE} it allows passing data to the same
+ * instance of the app on the primary user.
+ * <p>
+ * In both cases the application receives the data in
* {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
- * during the managed profile provisioning.
+ * during the managed provisioning.
*/
public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index f7d2821..353388d 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -246,41 +246,65 @@ public class TimeUtils {
public static final long NANOS_PER_MS = 1000000;
private static final Object sFormatSync = new Object();
- private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
-
- private static final long LARGEST_DURATION = (1000 * DateUtils.DAY_IN_MILLIS) - 1;
+ private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
+ private static char[] sTmpFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
static private int accumField(int amt, int suffix, boolean always, int zeropad) {
- if (amt > 99 || (always && zeropad >= 3)) {
- return 3+suffix;
- }
- if (amt > 9 || (always && zeropad >= 2)) {
- return 2+suffix;
- }
- if (always || amt > 0) {
- return 1+suffix;
+ if (amt > 999) {
+ int num = 0;
+ while (amt != 0) {
+ num++;
+ amt /= 10;
+ }
+ return num + suffix;
+ } else {
+ if (amt > 99 || (always && zeropad >= 3)) {
+ return 3+suffix;
+ }
+ if (amt > 9 || (always && zeropad >= 2)) {
+ return 2+suffix;
+ }
+ if (always || amt > 0) {
+ return 1+suffix;
+ }
}
return 0;
}
- static private int printField(char[] formatStr, int amt, char suffix, int pos,
+ static private int printFieldLocked(char[] formatStr, int amt, char suffix, int pos,
boolean always, int zeropad) {
if (always || amt > 0) {
final int startPos = pos;
- if ((always && zeropad >= 3) || amt > 99) {
- int dig = amt/100;
- formatStr[pos] = (char)(dig + '0');
- pos++;
- amt -= (dig*100);
- }
- if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
- int dig = amt/10;
- formatStr[pos] = (char)(dig + '0');
+ if (amt > 999) {
+ int tmp = 0;
+ while (amt != 0 && tmp < sTmpFormatStr.length) {
+ int dig = amt % 10;
+ sTmpFormatStr[tmp] = (char)(dig + '0');
+ tmp++;
+ amt /= 10;
+ }
+ tmp--;
+ while (tmp >= 0) {
+ formatStr[pos] = sTmpFormatStr[tmp];
+ pos++;
+ tmp--;
+ }
+ } else {
+ if ((always && zeropad >= 3) || amt > 99) {
+ int dig = amt/100;
+ formatStr[pos] = (char)(dig + '0');
+ pos++;
+ amt -= (dig*100);
+ }
+ if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
+ int dig = amt/10;
+ formatStr[pos] = (char)(dig + '0');
+ pos++;
+ amt -= (dig*10);
+ }
+ formatStr[pos] = (char)(amt + '0');
pos++;
- amt -= (dig*10);
}
- formatStr[pos] = (char)(amt + '0');
- pos++;
formatStr[pos] = suffix;
pos++;
}
@@ -312,10 +336,6 @@ public class TimeUtils {
duration = -duration;
}
- if (duration > LARGEST_DURATION) {
- duration = LARGEST_DURATION;
- }
-
int millis = (int)(duration%1000);
int seconds = (int) Math.floor(duration / 1000);
int days = 0, hours = 0, minutes = 0;
@@ -353,11 +373,11 @@ public class TimeUtils {
int start = pos;
boolean zeropad = fieldLen != 0;
- pos = printField(formatStr, days, 'd', pos, false, 0);
- pos = printField(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
- pos = printField(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
- pos = printField(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
- pos = printField(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
+ pos = printFieldLocked(formatStr, days, 'd', pos, false, 0);
+ pos = printFieldLocked(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
formatStr[pos] = 's';
return pos + 1;
}
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
index 52ea1c4..4cb617e 100644
--- a/core/tests/notificationtests/src/android/app/NotificationStressTest.java
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -77,15 +77,20 @@ public class NotificationStressTest extends InstrumentationTestCase {
}
private void sendNotification(int id, CharSequence text) {
- // Create "typical" notification with random icon
- Notification notification = new Notification(ICONS[mRandom.nextInt(ICONS.length)], text,
- System.currentTimeMillis());
// Fill in arbitrary content
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
CharSequence title = text + " " + id;
CharSequence subtitle = String.valueOf(System.currentTimeMillis());
- notification.setLatestEventInfo(mContext, title, subtitle, pendingIntent);
+ // Create "typical" notification with random icon
+ Notification notification = new Notification.Builder(mContext)
+ .setSmallIcon(ICONS[mRandom.nextInt(ICONS.length)])
+ .setTicker(text)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle(title)
+ .setContentText(subtitle)
+ .setContentIntent(pendingIntent)
+ .build();
mNotificationManager.notify(id, notification);
SystemClock.sleep(10);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index 19375a2..d2d5850 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -368,7 +368,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
byte[] output;
try {
- output = mMainDataStreamer.doFinal(input, inputOffset, inputLen);
+ byte[] additionalEntropy =
+ KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
+ mRng, getAdditionalEntropyAmountForFinish());
+ output = mMainDataStreamer.doFinal(input, inputOffset, inputLen, additionalEntropy);
} catch (KeyStoreException e) {
switch (e.getErrorCode()) {
case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
@@ -667,21 +670,37 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
/**
* Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
- * {@code begin} operation.
+ * {@code begin} operation. This amount of entropy is typically what's consumed to generate
+ * random parameters, such as IV.
*
- * <p>For decryption, this should be {@code 0} because decryption should not be consuming any
- * entropy. For encryption, this value should match (or exceed) the amount of Shannon entropy of
- * the ciphertext produced by this cipher assuming the key, the plaintext, and all explicitly
- * provided parameters to {@code Cipher.init} are known. For example, for AES CBC encryption
- * with an explicitly provided IV this should be {@code 0}, whereas for the case where IV is
- * generated by the KeyStore's {@code begin} operation this should be {@code 16}. For RSA with
- * OAEP this should be the size of the OAEP hash output. For RSA with PKCS#1 padding this should
- * be the size of the padding string or could be raised (for simplicity) to the size of the
- * modulus.
+ * <p>For decryption, the return value should be {@code 0} because decryption should not be
+ * consuming any entropy. For encryption, the value combined with
+ * {@link #getAdditionalEntropyAmountForFinish()} should match (or exceed) the amount of Shannon
+ * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
+ * explicitly provided parameters to {@code Cipher.init} are known. For example, for AES CBC
+ * encryption with an explicitly provided IV the return value should be {@code 0}, whereas for
+ * the case where IV is generated by the KeyStore's {@code begin} operation it should be
+ * {@code 16}.
*/
protected abstract int getAdditionalEntropyAmountForBegin();
/**
+ * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
+ * {@code finish} operation. This amount of entropy is typically what's consumed by encryption
+ * padding scheme.
+ *
+ * <p>For decryption, the return value should be {@code 0} because decryption should not be
+ * consuming any entropy. For encryption, the value combined with
+ * {@link #getAdditionalEntropyAmountForBegin()} should match (or exceed) the amount of Shannon
+ * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
+ * explicitly provided parameters to {@code Cipher.init} are known. For example, for RSA with
+ * OAEP the return value should be the size of the OAEP hash output. For RSA with PKCS#1 padding
+ * the return value should be the size of the padding string or could be raised (for simplicity)
+ * to the size of the modulus.
+ */
+ protected abstract int getAdditionalEntropyAmountForFinish();
+
+ /**
* Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
*
* @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
index 335da07..d19a766 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
@@ -117,7 +117,7 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
}
@Override
- protected int getAdditionalEntropyAmountForBegin() {
- return (isSigning()) ? mGroupSizeBytes : 0;
+ protected int getAdditionalEntropyAmountForSign() {
+ return mGroupSizeBytes;
}
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
index f31c06d..f7c184c 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
@@ -232,7 +232,10 @@ public abstract class AndroidKeyStoreHmacSpi extends MacSpi implements KeyStoreC
byte[] result;
try {
- result = mChunkedStreamer.doFinal(null, 0, 0);
+ result = mChunkedStreamer.doFinal(
+ null, 0, 0,
+ null // no additional entropy needed -- HMAC is deterministic
+ );
} catch (KeyStoreException e) {
throw new ProviderException("Keystore operation failed", e);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 35af34f..b93424d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -215,14 +215,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
- specBuilder.setDigests(
- KeyProperties.DIGEST_NONE,
- KeyProperties.DIGEST_MD5,
- KeyProperties.DIGEST_SHA1,
- KeyProperties.DIGEST_SHA224,
- KeyProperties.DIGEST_SHA256,
- KeyProperties.DIGEST_SHA384,
- KeyProperties.DIGEST_SHA512);
+ // Authorized to be used with any digest (including no digest).
+ specBuilder.setDigests(KeyProperties.DIGEST_NONE);
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
specBuilder = new KeyGenParameterSpec.Builder(
@@ -231,19 +225,13 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
| KeyProperties.PURPOSE_DECRYPT
| KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
- specBuilder.setDigests(
- KeyProperties.DIGEST_NONE,
- KeyProperties.DIGEST_MD5,
- KeyProperties.DIGEST_SHA1,
- KeyProperties.DIGEST_SHA224,
- KeyProperties.DIGEST_SHA256,
- KeyProperties.DIGEST_SHA384,
- KeyProperties.DIGEST_SHA512);
+ // Authorized to be used with any digest (including no digest).
+ specBuilder.setDigests(KeyProperties.DIGEST_NONE);
specBuilder.setSignaturePaddings(
KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
+ // Authorized to be used with any padding (including no padding).
specBuilder.setEncryptionPaddings(
- KeyProperties.ENCRYPTION_PADDING_NONE,
- KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
+ KeyProperties.ENCRYPTION_PADDING_NONE);
// Disable randomized encryption requirement to support encryption
// padding NONE above.
specBuilder.setRandomizedEncryptionRequired(false);
@@ -703,6 +691,36 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
}
case KeymasterDefs.KM_ALGORITHM_RSA:
{
+ // Check whether this key is authorized for PKCS#1 signature padding.
+ // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
+ // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
+ // to be authorized for PKCS#1 padding or padding NONE which means any padding.
+ boolean pkcs1SignaturePaddingSupported = false;
+ for (int keymasterPadding : KeyProperties.SignaturePadding.allToKeymaster(
+ spec.getSignaturePaddings())) {
+ if ((keymasterPadding == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN)
+ || (keymasterPadding == KeymasterDefs.KM_PAD_NONE)) {
+ pkcs1SignaturePaddingSupported = true;
+ break;
+ }
+ }
+ if (!pkcs1SignaturePaddingSupported) {
+ // Keymaster doesn't distinguish between encryption padding NONE and signature
+ // padding NONE. In the Android Keystore API only encryption padding NONE is
+ // exposed.
+ for (int keymasterPadding : KeyProperties.EncryptionPadding.allToKeymaster(
+ spec.getEncryptionPaddings())) {
+ if (keymasterPadding == KeymasterDefs.KM_PAD_NONE) {
+ pkcs1SignaturePaddingSupported = true;
+ break;
+ }
+ }
+ }
+ if (!pkcs1SignaturePaddingSupported) {
+ // Key not authorized for PKCS#1 signature padding -- can't sign
+ return null;
+ }
+
Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
spec.getDigests(),
AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
index d33692a..6abdf19 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
@@ -99,6 +99,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
@Override
+ protected final int getAdditionalEntropyAmountForFinish() {
+ return 0;
+ }
+
+ @Override
@NonNull
protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
KeyStore keyStore, IBinder operationToken) {
@@ -142,7 +147,8 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
@Override
- public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
+ public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
+ byte[] additionalEntropy)
throws KeyStoreException {
if (inputLength > 0) {
mInputBuffer.write(input, inputOffset, inputLength);
@@ -165,7 +171,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
"Message size (" + bufferedInput.length + " bytes) must be smaller than"
+ " modulus (" + mModulusSizeBytes + " bytes)");
}
- return mDelegate.doFinal(paddedInput, 0, paddedInput.length);
+ return mDelegate.doFinal(paddedInput, 0, paddedInput.length, additionalEntropy);
}
}
}
@@ -207,6 +213,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
@Override
protected final int getAdditionalEntropyAmountForBegin() {
+ return 0;
+ }
+
+ @Override
+ protected final int getAdditionalEntropyAmountForFinish() {
return (isEncrypting()) ? getModulusSizeBytes() : 0;
}
}
@@ -361,6 +372,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
@Override
protected final int getAdditionalEntropyAmountForBegin() {
+ return 0;
+ }
+
+ @Override
+ protected final int getAdditionalEntropyAmountForFinish() {
return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
}
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
index 898336d..954b71a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
@@ -36,7 +36,7 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
}
@Override
- protected final int getAdditionalEntropyAmountForBegin() {
+ protected final int getAdditionalEntropyAmountForSign() {
// No entropy required for this deterministic signature scheme.
return 0;
}
@@ -92,8 +92,8 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
}
@Override
- protected final int getAdditionalEntropyAmountForBegin() {
- return (isSigning()) ? SALT_LENGTH_BYTES : 0;
+ protected final int getAdditionalEntropyAmountForSign() {
+ return SALT_LENGTH_BYTES;
}
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
index f072ae7..5cdcc41 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
@@ -198,15 +198,14 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
KeymasterArguments keymasterInputArgs = new KeymasterArguments();
addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
- byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
- appRandom, getAdditionalEntropyAmountForBegin());
OperationResult opResult = mKeyStore.begin(
mKey.getAlias(),
mSigning ? KeymasterDefs.KM_PURPOSE_SIGN : KeymasterDefs.KM_PURPOSE_VERIFY,
true, // permit aborting this operation if keystore runs out of resources
keymasterInputArgs,
- additionalEntropy);
+ null // no additional entropy for begin -- only finish might need some
+ );
if (opResult == null) {
throw new KeyStoreConnectException();
}
@@ -311,7 +310,11 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
byte[] signature;
try {
ensureKeystoreOperationInitialized();
- signature = mMessageStreamer.doFinal(EmptyArray.BYTE, 0, 0);
+
+ byte[] additionalEntropy =
+ KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
+ appRandom, getAdditionalEntropyAmountForSign());
+ signature = mMessageStreamer.doFinal(EmptyArray.BYTE, 0, 0, additionalEntropy);
} catch (InvalidKeyException | KeyStoreException e) {
throw new SignatureException(e);
}
@@ -388,15 +391,14 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
/**
* Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
- * {@code begin} operation.
+ * {@code finish} operation when generating a signature.
*
- * <p>For signature verification, this should be {@code 0} because verification should not be
- * consuming any entropy. For signature generation, this value should match (or exceed) the
- * amount of Shannon entropy of the produced signature assuming the key and the message are
- * known. For example, for ECDSA signature this should be the size of {@code R}, whereas for the
- * RSA signature with PKCS#1 padding this should be {@code 0}.
+ * <p>This value should match (or exceed) the amount of Shannon entropy of the produced
+ * signature assuming the key and the message are known. For example, for ECDSA signature this
+ * should be the size of {@code R}, whereas for the RSA signature with PKCS#1 padding this
+ * should be {@code 0}.
*/
- protected abstract int getAdditionalEntropyAmountForBegin();
+ protected abstract int getAdditionalEntropyAmountForSign();
/**
* Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 831a106..3bd9d1d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -247,14 +247,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
specBuilder =
new KeyProtection.Builder(
KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
- specBuilder.setDigests(
- KeyProperties.DIGEST_NONE,
- KeyProperties.DIGEST_MD5,
- KeyProperties.DIGEST_SHA1,
- KeyProperties.DIGEST_SHA224,
- KeyProperties.DIGEST_SHA256,
- KeyProperties.DIGEST_SHA384,
- KeyProperties.DIGEST_SHA512);
+ // Authorized to be used with any digest (including no digest).
+ specBuilder.setDigests(KeyProperties.DIGEST_NONE);
} else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
specBuilder =
new KeyProtection.Builder(
@@ -262,19 +256,13 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
| KeyProperties.PURPOSE_DECRYPT
| KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
- specBuilder.setDigests(
- KeyProperties.DIGEST_NONE,
- KeyProperties.DIGEST_MD5,
- KeyProperties.DIGEST_SHA1,
- KeyProperties.DIGEST_SHA224,
- KeyProperties.DIGEST_SHA256,
- KeyProperties.DIGEST_SHA384,
- KeyProperties.DIGEST_SHA512);
+ // Authorized to be used with any digest (including no digest).
+ specBuilder.setDigests(KeyProperties.DIGEST_NONE);
specBuilder.setSignaturePaddings(
KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
+ // Authorized to be used with any padding (including no padding).
specBuilder.setEncryptionPaddings(
- KeyProperties.ENCRYPTION_PADDING_NONE,
- KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
+ KeyProperties.ENCRYPTION_PADDING_NONE);
// Disable randomized encryption requirement to support encryption padding NONE
// above.
specBuilder.setRandomizedEncryptionRequired(false);
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
index 47cd1d1..76804a9 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
@@ -210,6 +210,11 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
}
@Override
+ protected final int getAdditionalEntropyAmountForFinish() {
+ return 0;
+ }
+
+ @Override
protected final void addAlgorithmSpecificParametersToBegin(
@NonNull KeymasterArguments keymasterArgs) {
if ((isEncrypting()) && (mIvRequired) && (mIvHasBeenUsed)) {
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 68c9c79..47aab74 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -611,9 +611,14 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
*
* <p>This must be specified for keys which are used for signing/verification. For HMAC
* keys, the set of digests defaults to the digest associated with the key algorithm (e.g.,
- * {@code SHA-256} for key algorithm {@code HmacSHA256}
+ * {@code SHA-256} for key algorithm {@code HmacSHA256}).
*
- * @see KeyProperties.Digest
+ * <p>For private keys used for TLS/SSL client or server authentication it is usually
+ * necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
+ * because TLS/SSL stacks typically generate the necessary digest(s) themselves and then use
+ * a private key to sign it.
+ *
+ * <p>See {@link KeyProperties}.{@code DIGEST} constants.
*/
@NonNull
public Builder setDigests(@KeyProperties.DigestEnum String... digests) {
@@ -629,6 +634,12 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
*
* <p>This must be specified for keys which are used for encryption/decryption.
*
+ * <p>For RSA private keys used by TLS/SSL servers to authenticate themselves to clients it
+ * is usually necessary to authorize the use of no/any padding
+ * ({@link KeyProperties#ENCRYPTION_PADDING_NONE}). This is because RSA decryption is
+ * required by some cipher suites, and some stacks request decryption using no padding
+ * whereas others request PKCS#1 padding.
+ *
* <p>See {@link KeyProperties}.{@code ENCRYPTION_PADDING} constants.
*/
@NonNull
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 5af4181..403e814 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -368,6 +368,9 @@ public abstract class KeyProperties {
/**
* No encryption padding.
+ *
+ * <p><b>NOTE</b>: If a key is authorized to be used with no padding, then it can be used with
+ * any padding scheme.
*/
public static final String ENCRYPTION_PADDING_NONE = "NoPadding";
@@ -514,6 +517,9 @@ public abstract class KeyProperties {
/**
* No digest: sign/authenticate the raw message.
+ *
+ * <p><b>NOTE</b>: If a key is authorized to be used with no digest, then it can be used with
+ * any digest.
*/
public static final String DIGEST_NONE = "NONE";
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 48c0ed0..432fc12 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -374,6 +374,12 @@ public final class KeyProtection implements ProtectionParameter {
*
* <p>This must be specified for keys which are used for encryption/decryption.
*
+ * <p>For RSA private keys used by TLS/SSL servers to authenticate themselves to clients it
+ * is usually necessary to authorize the use of no/any padding
+ * ({@link KeyProperties#ENCRYPTION_PADDING_NONE}). This is because RSA decryption is
+ * required by some cipher suites, and some stacks request decryption using no padding
+ * whereas others request PKCS#1 padding.
+ *
* <p>See {@link KeyProperties}.{@code ENCRYPTION_PADDING} constants.
*/
@NonNull
@@ -408,6 +414,11 @@ public final class KeyProtection implements ProtectionParameter {
* {@link Key#getAlgorithm()}. For asymmetric signing keys the set of digest algorithms
* must be specified.
*
+ * <p>For private keys used for TLS/SSL client or server authentication it is usually
+ * necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
+ * because TLS/SSL stacks typically generate the necessary digest(s) themselves and then use
+ * a private key to sign it.
+ *
* <p>See {@link KeyProperties}.{@code DIGEST} constants.
*/
@NonNull
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index 47b4996..9957e79 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -35,8 +35,8 @@ import java.io.IOException;
* amount of data in one go because the operations are marshalled via Binder. Secondly, the update
* operation may consume less data than provided, in which case the caller has to buffer the
* remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
- * {@link #doFinal(byte[], int, int) doFinal} operations which can be used to conveniently implement
- * various JCA crypto primitives.
+ * {@link #doFinal(byte[], int, int, byte[]) doFinal} operations which can be used to conveniently
+ * implement various JCA crypto primitives.
*
* <p>Bidirectional chunked streaming of data via a KeyStore crypto operation is abstracted away as
* a {@link Stream} to avoid having this class deal with operation tokens and occasional additional
@@ -60,7 +60,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS
* Returns the result of the KeyStore {@code finish} operation or null if keystore couldn't
* be reached.
*/
- OperationResult finish();
+ OperationResult finish(byte[] additionalEntropy);
}
// Binder buffer is about 1MB, but it's shared between all active transactions of the process.
@@ -192,7 +192,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS
}
@Override
- public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
+ public byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] additionalEntropy)
throws KeyStoreException {
if (inputLength == 0) {
// No input provided -- simplify the rest of the code
@@ -204,7 +204,7 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS
byte[] output = update(input, inputOffset, inputLength);
output = ArrayUtils.concat(output, flush());
- OperationResult opResult = mKeyStoreStream.finish();
+ OperationResult opResult = mKeyStoreStream.finish(additionalEntropy);
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
@@ -268,8 +268,8 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS
}
@Override
- public OperationResult finish() {
- return mKeyStore.finish(mOperationToken, null, null);
+ public OperationResult finish(byte[] additionalEntropy) {
+ return mKeyStore.finish(mOperationToken, null, null, additionalEntropy);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
index 2fb8f20..1c6de2d 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
@@ -28,12 +28,13 @@ import android.security.KeyStoreException;
* amount of data in one go because the operations are marshalled via Binder. Secondly, the update
* operation may consume less data than provided, in which case the caller has to buffer the
* remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
- * {@link #doFinal(byte[], int, int) doFinal} operations which can be used to conveniently implement
- * various JCA crypto primitives.
+ * {@link #doFinal(byte[], int, int, byte[]) doFinal} operations which can be used to conveniently
+ * implement various JCA crypto primitives.
*
* @hide
*/
interface KeyStoreCryptoOperationStreamer {
byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
- byte[] doFinal(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
+ byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] additionalEntropy)
+ throws KeyStoreException;
}
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 95b3eb3..260f380 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -172,7 +172,7 @@ public class GpsNetInitiatedHandler {
* <p>
* This is lazily created, so use {@link #setNINotification()}.
*/
- private Notification mNiNotification;
+ private Notification.Builder mNiNotificationBuilder;
public GpsNetInitiatedHandler(Context context,
INetInitiatedListener netInitiatedListener,
@@ -367,29 +367,31 @@ public class GpsNetInitiatedHandler {
", message: " + message);
// Construct Notification
- if (mNiNotification == null) {
- mNiNotification = new Notification();
- mNiNotification.icon = com.android.internal.R.drawable.stat_sys_gps_on; /* Change notification icon here */
- mNiNotification.when = 0;
+ if (mNiNotificationBuilder == null) {
+ mNiNotificationBuilder = new Notification.Builder(mContext)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
+ .setWhen(0)
+ .setOngoing(true)
+ .setAutoCancel(true)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
}
if (mPlaySounds) {
- mNiNotification.defaults |= Notification.DEFAULT_SOUND;
+ mNiNotificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
} else {
- mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
+ mNiNotificationBuilder.setDefaults(0);
}
- mNiNotification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
- mNiNotification.tickerText = getNotifTicker(notif, mContext);
-
// if not to popup dialog immediately, pending intent will open the dialog
Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
- mNiNotification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- mNiNotification.setLatestEventInfo(mContext, title, message, pi);
+ mNiNotificationBuilder.setTicker(getNotifTicker(notif, mContext))
+ .setContentTitle(title)
+ .setContentText(message)
+ .setContentIntent(pi);
- notificationManager.notifyAsUser(null, notif.notificationId, mNiNotification,
+ notificationManager.notifyAsUser(null, notif.notificationId, mNiNotificationBuilder.build(),
UserHandle.ALL);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 742f570..26ece72 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -47,6 +47,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
import android.util.TimeUtils;
import java.io.ByteArrayOutputStream;
@@ -84,6 +85,12 @@ class AlarmManagerService extends SystemService {
// Minimum alarm recurrence interval
private static final long MIN_INTERVAL = 60 * 1000; // one minute, in millis
+ // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
+ private static final long ALLOW_WHILE_IDLE_SHORT_TIME = 60*1000;
+
+ // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
+ private static final long ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
+
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
@@ -123,8 +130,8 @@ class AlarmManagerService extends SystemService {
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
boolean mLastWakeLockUnimportantForLogging;
- ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
- ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
+ ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
+ ArrayList<InFlight> mInFlight = new ArrayList<>();
final AlarmHandler mHandler = new AlarmHandler();
ClockReceiver mClockReceiver;
InteractiveStateReceiver mInteractiveStateReceiver;
@@ -141,8 +148,15 @@ class AlarmManagerService extends SystemService {
long mNextNonWakeupDeliveryTime;
long mLastTimeChangeClockTime;
long mLastTimeChangeRealtime;
+ long mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_SHORT_TIME;
int mNumTimeChanged;
+ /**
+ * For each uid, this is the last time we dispatched an "allow while idle" alarm,
+ * used to determine the earliest we can dispatch the next such alarm.
+ */
+ final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
+
private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
new SparseArray<>();
private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
@@ -552,7 +566,7 @@ class AlarmManagerService extends SystemService {
a.when = a.origWhen;
long whenElapsed = convertToElapsed(a.when, a.type);
final long maxElapsed;
- if (a.whenElapsed == a.maxWhenElapsed) {
+ if (a.windowLength == AlarmManager.WINDOW_EXACT) {
// Exact
maxElapsed = whenElapsed;
} else {
@@ -580,6 +594,9 @@ class AlarmManagerService extends SystemService {
}
}
+ // Make sure we are using the correct ALLOW_WHILE_IDLE min time.
+ mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_SHORT_TIME;
+
// Reschedule everything.
rescheduleKernelAlarmsLocked();
updateNextAlarmClockLocked();
@@ -632,7 +649,7 @@ class AlarmManagerService extends SystemService {
mTag = tag;
}
}
-
+
static final class BroadcastStats {
final int mUid;
final String mPackageName;
@@ -649,7 +666,7 @@ class AlarmManagerService extends SystemService {
mPackageName = packageName;
}
}
-
+
final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
= new SparseArray<ArrayMap<String, BroadcastStats>>();
@@ -751,7 +768,7 @@ class AlarmManagerService extends SystemService {
void setImpl(int type, long triggerAtTime, long windowLength, long interval,
PendingIntent operation, int flags, WorkSource workSource,
- AlarmManager.AlarmClockInfo alarmClock) {
+ AlarmManager.AlarmClockInfo alarmClock, int callingUid) {
if (operation == null) {
Slog.w(TAG, "set/setRepeating ignored because there is no intent");
return;
@@ -779,9 +796,8 @@ class AlarmManagerService extends SystemService {
}
if (triggerAtTime < 0) {
- final long who = Binder.getCallingUid();
final long what = Binder.getCallingPid();
- Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + who
+ Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
+ " pid=" + what);
triggerAtTime = 0;
}
@@ -797,12 +813,12 @@ class AlarmManagerService extends SystemService {
maxElapsed = triggerElapsed;
} else if (windowLength < 0) {
maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
+ // Fix this window in place, so that as time approaches we don't collapse it.
+ windowLength = maxElapsed - triggerElapsed;
} else {
maxElapsed = triggerElapsed + windowLength;
}
- final int userId = UserHandle.getCallingUserId();
-
synchronized (mLock) {
if (DEBUG_BATCH) {
Slog.v(TAG, "set(" + operation + ") : type=" + type
@@ -811,26 +827,20 @@ class AlarmManagerService extends SystemService {
+ " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
}
setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
- interval, operation, flags, true, workSource, alarmClock, userId);
+ interval, operation, flags, true, workSource, alarmClock, callingUid);
}
}
private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
long maxWhen, long interval, PendingIntent operation, int flags,
boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
- int userId) {
+ int uid) {
Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
- operation, workSource, flags, alarmClock, userId);
+ operation, workSource, flags, alarmClock, uid);
removeLocked(operation);
setImplLocked(a, false, doValidate);
}
- private void updateNextWakeFromIdleFuzzLocked() {
- if (mNextWakeFromIdle != null) {
-
- }
- }
-
private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
// This is a special alarm that will put the system into idle until it goes off.
@@ -862,7 +872,9 @@ class AlarmManagerService extends SystemService {
} else if (mPendingIdleUntil != null) {
// We currently have an idle until alarm scheduled; if the new alarm has
// not explicitly stated it wants to run while idle, then put it on hold.
- if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE|AlarmManager.FLAG_WAKE_FROM_IDLE))
+ if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
+ | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
+ | AlarmManager.FLAG_WAKE_FROM_IDLE))
== 0) {
mPendingWhileIdleAlarms.add(a);
return;
@@ -892,6 +904,7 @@ class AlarmManagerService extends SystemService {
if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
mPendingIdleUntil = a;
+ mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_LONG_TIME;
needRebatch = true;
} else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
@@ -933,23 +946,45 @@ class AlarmManagerService extends SystemService {
public void set(int type, long triggerAtTime, long windowLength, long interval, int flags,
PendingIntent operation, WorkSource workSource,
AlarmManager.AlarmClockInfo alarmClock) {
+ final int callingUid = Binder.getCallingUid();
if (workSource != null) {
- getContext().enforceCallingPermission(
+ getContext().enforcePermission(
android.Manifest.permission.UPDATE_DEVICE_STATS,
- "AlarmManager.set");
+ Binder.getCallingPid(), callingUid, "AlarmManager.set");
+ }
+
+ // No incoming callers can request either WAKE_FROM_IDLE or
+ // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
+ flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
+ | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
+
+ // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
+ // manager when to come out of idle mode, which is only for DeviceIdleController.
+ if (callingUid != Process.SYSTEM_UID) {
+ flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
+ }
+
+ // If the caller is a core system component, and not calling to do work on behalf
+ // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED. This means we
+ // will allow these alarms to go off as normal even while idle, with no timing
+ // restrictions.
+ if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
+ flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
}
+ // If this is an exact time alarm, then it can't be batched with other alarms.
if (windowLength == AlarmManager.WINDOW_EXACT) {
flags |= AlarmManager.FLAG_STANDALONE;
}
+
+ // If this alarm is for an alarm clock, then it must be standalone and we will
+ // use it to wake early from idle if needed.
if (alarmClock != null) {
flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
}
- if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
- flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE;
- }
+
setImpl(type, triggerAtTime, windowLength, interval, operation,
- flags, workSource, alarmClock);
+ flags, workSource, alarmClock, callingUid);
}
@Override
@@ -1126,6 +1161,22 @@ class AlarmManagerService extends SystemService {
pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
pw.println();
+ pw.print("mAllowWhileIdleMinTime=");
+ TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
+ pw.println();
+ if (mLastAllowWhileIdleDispatch.size() > 0) {
+ pw.println("Last allow while idle dispatch times:");
+ for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
+ pw.print(" UID ");
+ UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
+ pw.print(": ");
+ TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
+ nowELAPSED, pw);
+ pw.println();
+ }
+ }
+ pw.println();
+
if (mLog.dump(pw, " Recent problems", " ")) {
pw.println();
}
@@ -1322,7 +1373,7 @@ class AlarmManagerService extends SystemService {
for (int j = 0; j < M; j++) {
Alarm a = alarms.get(j);
if (a.alarmClock != null) {
- final int userId = a.userId;
+ final int userId = UserHandle.getUserId(a.uid);
if (DEBUG_ALARM_CLOCK) {
Log.v(TAG, "Found AlarmClockInfo at " +
@@ -1531,6 +1582,11 @@ class AlarmManagerService extends SystemService {
mPendingWhileIdleAlarms.remove(i);
}
}
+ for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
+ if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
+ mLastAllowWhileIdleDispatch.removeAt(i);
+ }
+ }
if (didRemove) {
if (DEBUG_BATCH) {
@@ -1666,6 +1722,25 @@ class AlarmManagerService extends SystemService {
final int N = batch.size();
for (int i = 0; i < N; i++) {
Alarm alarm = batch.get(i);
+
+ if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+ // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
+ // schedule such alarms.
+ long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
+ long minTime = lastTime + mAllowWhileIdleMinTime;
+ if (nowELAPSED < minTime) {
+ // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
+ // alarm went off for this app. Reschedule the alarm to be in the
+ // correct time period.
+ alarm.whenElapsed = minTime;
+ if (alarm.maxWhenElapsed < minTime) {
+ alarm.maxWhenElapsed = minTime;
+ }
+ setImplLocked(alarm, true, false);
+ continue;
+ }
+ }
+
alarm.count = 1;
triggerList.add(alarm);
if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
@@ -1695,7 +1770,7 @@ class AlarmManagerService extends SystemService {
setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
alarm.repeatInterval, alarm.operation, alarm.flags, true,
- alarm.workSource, alarm.alarmClock, alarm.userId);
+ alarm.workSource, alarm.alarmClock, alarm.uid);
}
if (alarm.wakeup) {
@@ -1749,19 +1824,19 @@ class AlarmManagerService extends SystemService {
public final String tag;
public final WorkSource workSource;
public final int flags;
+ public final AlarmManager.AlarmClockInfo alarmClock;
+ public final int uid;
public int count;
public long when;
public long windowLength;
public long whenElapsed; // 'when' in the elapsed time base
public long maxWhenElapsed; // also in the elapsed time base
public long repeatInterval;
- public final AlarmManager.AlarmClockInfo alarmClock;
- public final int userId;
public PriorityClass priorityClass;
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws, int _flags,
- AlarmManager.AlarmClockInfo _info, int _userId) {
+ AlarmManager.AlarmClockInfo _info, int _uid) {
type = _type;
origWhen = _when;
wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
@@ -1776,7 +1851,7 @@ class AlarmManagerService extends SystemService {
workSource = _ws;
flags = _flags;
alarmClock = _info;
- userId = _userId;
+ uid = _uid;
}
public static String makeTag(PendingIntent pi, int type) {
@@ -1812,7 +1887,7 @@ class AlarmManagerService extends SystemService {
pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
}
pw.println();
- pw.print(prefix); pw.print("window="); pw.print(windowLength);
+ pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
pw.print(" repeatInterval="); pw.print(repeatInterval);
pw.print(" count="); pw.print(count);
pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
@@ -1925,6 +2000,11 @@ class AlarmManagerService extends SystemService {
mInFlight.add(inflight);
mBroadcastRefCount++;
+ if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+ // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
+ mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
+ }
+
final BroadcastStats bs = inflight.mBroadcastStats;
bs.count++;
if (bs.nesting == 0) {
@@ -2196,7 +2276,8 @@ class AlarmManagerService extends SystemService {
final WorkSource workSource = null; // Let system take blame for time tick events.
setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
- 0, mTimeTickSender, AlarmManager.FLAG_STANDALONE, workSource, null);
+ 0, mTimeTickSender, AlarmManager.FLAG_STANDALONE, workSource, null,
+ Process.myUid());
}
public void scheduleDateChangedEvent() {
@@ -2210,7 +2291,7 @@ class AlarmManagerService extends SystemService {
final WorkSource workSource = null; // Let system take blame for date change events.
setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender,
- AlarmManager.FLAG_STANDALONE, workSource, null);
+ AlarmManager.FLAG_STANDALONE, workSource, null, Process.myUid());
}
}
@@ -2243,6 +2324,7 @@ class AlarmManagerService extends SystemService {
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED);
+ sdFilter.addAction(Intent.ACTION_UID_REMOVED);
getContext().registerReceiver(this, sdFilter);
}
@@ -2267,6 +2349,11 @@ class AlarmManagerService extends SystemService {
if (userHandle >= 0) {
removeUserLocked(userHandle);
}
+ } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ if (uid >= 0) {
+ mLastAllowWhileIdleDispatch.delete(uid);
+ }
} else {
if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
&& intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9c6e16f..f645764 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3289,7 +3289,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
CharSequence title;
CharSequence details;
int icon;
- Notification notification = new Notification();
if (notifyType == NotificationType.NO_INTERNET &&
networkType == ConnectivityManager.TYPE_WIFI) {
title = r.getString(R.string.wifi_no_internet, 0);
@@ -3324,14 +3323,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
return;
}
- notification.when = 0;
- notification.icon = icon;
- notification.flags = Notification.FLAG_AUTO_CANCEL;
- notification.tickerText = title;
- notification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
- notification.contentIntent = intent;
+ Notification notification = new Notification.Builder(mContext)
+ .setWhen(0)
+ .setSmallIcon(icon)
+ .setAutoCancel(true)
+ .setTicker(title)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(details)
+ .setContentIntent(intent)
+ .build();
try {
notificationManager.notify(NOTIFICATION_ID, id, notification);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6e6fb7f..a5d536e 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -71,6 +71,7 @@ import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
@@ -212,7 +213,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private NotificationManager mNotificationManager;
private KeyguardManager mKeyguardManager;
private StatusBarManagerService mStatusBar;
- private Notification mImeSwitcherNotification;
+ private Notification.Builder mImeSwitcherNotification;
private PendingIntent mImeSwitchPendingIntent;
private boolean mShowOngoingImeSwitcherForPhones;
private boolean mNotificationShown;
@@ -798,18 +799,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mHasFeature = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS);
- mImeSwitcherNotification = new Notification();
- mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
- mImeSwitcherNotification.when = 0;
- mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mImeSwitcherNotification.tickerText = null;
- mImeSwitcherNotification.defaults = 0; // please be quiet
- mImeSwitcherNotification.sound = null;
- mImeSwitcherNotification.vibrate = null;
-
- // Tag this notification specially so SystemUI knows it's important
- mImeSwitcherNotification.extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
- mImeSwitcherNotification.category = Notification.CATEGORY_SYSTEM;
+ Bundle extras = new Bundle();
+ extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
+ mImeSwitcherNotification = new Notification.Builder(mContext)
+ .setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
+ .setWhen(0)
+ .setOngoing(true)
+ .addExtras(extras)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setColor(com.android.internal.R.color.system_notification_accent_color);
Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
@@ -1766,11 +1764,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
com.android.internal.R.string.select_input_method);
final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
mContext, imi, mCurrentSubtype);
-
- mImeSwitcherNotification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- mImeSwitcherNotification.setLatestEventInfo(
- mContext, title, summary, mImeSwitchPendingIntent);
+ mImeSwitcherNotification.setContentTitle(title)
+ .setContentText(summary)
+ .setContentIntent(mImeSwitchPendingIntent);
if ((mNotificationManager != null)
&& !mWindowManagerService.hasNavigationBar()) {
if (DEBUG) {
@@ -1778,7 +1774,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
mNotificationManager.notifyAsUser(null,
com.android.internal.R.string.select_input_method,
- mImeSwitcherNotification, UserHandle.ALL);
+ mImeSwitcherNotification.build(), UserHandle.ALL);
mNotificationShown = true;
}
} else {
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 64f3070..0b67ad8 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -601,21 +601,22 @@ final class UiModeManagerService extends SystemService {
if (mCarModeEnabled) {
Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class);
- Notification n = new Notification();
- n.icon = R.drawable.stat_notify_car_mode;
- n.defaults = Notification.DEFAULT_LIGHTS;
- n.flags = Notification.FLAG_ONGOING_EVENT;
- n.when = 0;
- n.color = context.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- n.setLatestEventInfo(
- context,
- context.getString(R.string.car_mode_disable_notification_title),
- context.getString(R.string.car_mode_disable_notification_message),
- PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
- null, UserHandle.CURRENT));
+ Notification.Builder n = new Notification.Builder(context)
+ .setSmallIcon(R.drawable.stat_notify_car_mode)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .setOngoing(true)
+ .setWhen(0)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(
+ context.getString(R.string.car_mode_disable_notification_title))
+ .setContentText(
+ context.getString(R.string.car_mode_disable_notification_message))
+ .setContentIntent(
+ PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
+ null, UserHandle.CURRENT));
mNotificationManager.notifyAsUser(null,
- R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
+ R.string.car_mode_disable_notification_title, n.build(), UserHandle.ALL);
} else {
mNotificationManager.cancelAsUser(null,
R.string.car_mode_disable_notification_title, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 49d9988..3456dbc 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2005,8 +2005,6 @@ public class AccountManagerService
String authTokenLabel = intent.getStringExtra(
GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
- Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
- 0 /* when */);
final String titleAndSubtitle =
mContext.getString(R.string.permission_request_notification_with_subtitle,
account.name);
@@ -2019,11 +2017,16 @@ public class AccountManagerService
}
UserHandle user = new UserHandle(userId);
Context contextForUser = getContextForUser(user);
- n.color = contextForUser.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- n.setLatestEventInfo(contextForUser, title, subtitle,
- PendingIntent.getActivityAsUser(mContext, 0, intent,
- PendingIntent.FLAG_CANCEL_CURRENT, null, user));
+ Notification n = new Notification.Builder(contextForUser)
+ .setSmallIcon(android.R.drawable.stat_sys_warning)
+ .setWhen(0)
+ .setColor(contextForUser.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(subtitle)
+ .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT, null, user))
+ .build();
installNotification(getCredentialPermissionNotificationId(
account, authTokenType, uid), n, user);
}
@@ -3542,19 +3545,21 @@ public class AccountManagerService
} else {
final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
intent.addCategory(String.valueOf(notificationId));
- Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
- 0 /* when */);
UserHandle user = new UserHandle(userId);
Context contextForUser = getContextForUser(user);
final String notificationTitleFormat =
contextForUser.getText(R.string.notification_title).toString();
- n.color = contextForUser.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- n.setLatestEventInfo(contextForUser,
- String.format(notificationTitleFormat, account.name),
- message, PendingIntent.getActivityAsUser(
- mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
- null, user));
+ Notification n = new Notification.Builder(contextForUser)
+ .setWhen(0)
+ .setSmallIcon(android.R.drawable.stat_sys_warning)
+ .setColor(contextForUser.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(String.format(notificationTitleFormat, account.name))
+ .setContentText(message)
+ .setContentIntent(PendingIntent.getActivityAsUser(
+ mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
+ null, user))
+ .build();
installNotification(notificationId, n, user);
}
} finally {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 029a3b2..421ba86 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1714,22 +1714,20 @@ public final class ActivityManagerService extends ActivityManagerNative
Context context = mContext.createPackageContext(process.info.packageName, 0);
String text = mContext.getString(R.string.heavy_weight_notification,
context.getApplicationInfo().loadLabel(context.getPackageManager()));
- Notification notification = new Notification();
- notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
- notification.when = 0;
- notification.flags = Notification.FLAG_ONGOING_EVENT;
- notification.tickerText = text;
- notification.defaults = 0; // please be quiet
- notification.sound = null;
- notification.vibrate = null;
- notification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- notification.setLatestEventInfo(context, text,
- mContext.getText(R.string.heavy_weight_notification_detail),
- PendingIntent.getActivityAsUser(mContext, 0, root.intent,
- PendingIntent.FLAG_CANCEL_CURRENT, null,
- new UserHandle(root.userId)));
-
+ Notification notification = new Notification.Builder(context)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setWhen(0)
+ .setOngoing(true)
+ .setTicker(text)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(text)
+ .setContentText(
+ mContext.getText(R.string.heavy_weight_notification_detail))
+ .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+ root.intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+ new UserHandle(root.userId)))
+ .build();
try {
int[] outId = new int[1];
inm.enqueueNotificationWithTag("android", "android", null,
@@ -1948,20 +1946,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
String text = mContext.getString(R.string.dump_heap_notification, procName);
- Notification notification = new Notification();
- notification.icon = com.android.internal.R.drawable.stat_sys_adb;
- notification.when = 0;
- notification.flags = Notification.FLAG_ONGOING_EVENT|Notification.FLAG_AUTO_CANCEL;
- notification.tickerText = text;
- notification.defaults = 0; // please be quiet
- notification.sound = null;
- notification.vibrate = null;
- notification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
+
+
Intent deleteIntent = new Intent();
deleteIntent.setAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP);
- notification.deleteIntent = PendingIntent.getBroadcastAsUser(mContext, 0,
- deleteIntent, 0, UserHandle.OWNER);
Intent intent = new Intent();
intent.setClassName("android", DumpHeapActivity.class.getName());
intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName);
@@ -1970,11 +1958,23 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage);
}
int userId = UserHandle.getUserId(uid);
- notification.setLatestEventInfo(mContext, text,
- mContext.getText(R.string.dump_heap_notification_detail),
- PendingIntent.getActivityAsUser(mContext, 0, intent,
- PendingIntent.FLAG_CANCEL_CURRENT, null,
- new UserHandle(userId)));
+ Notification notification = new Notification.Builder(mContext)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setWhen(0)
+ .setOngoing(true)
+ .setAutoCancel(true)
+ .setTicker(text)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(text)
+ .setContentText(
+ mContext.getText(R.string.dump_heap_notification_detail))
+ .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+ intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+ new UserHandle(userId)))
+ .setDeleteIntent(PendingIntent.getBroadcastAsUser(mContext, 0,
+ deleteIntent, 0, UserHandle.OWNER))
+ .build();
try {
int[] outId = new int[1];
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 897300f..c1aaf07 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -130,7 +130,8 @@ public class Tethering extends BaseNetworkObserver {
private StateMachine mTetherMasterSM;
- private Notification mTetheredNotification;
+ private Notification.Builder mTetheredNotificationBuilder;
+ private int mLastNotificationId;
private boolean mRndisEnabled; // track the RNDIS function enabled state
private boolean mUsbTetherRequested; // true if USB tethering should be started
@@ -450,12 +451,13 @@ public class Tethering extends BaseNetworkObserver {
return;
}
- if (mTetheredNotification != null) {
- if (mTetheredNotification.icon == icon) {
+ if (mLastNotificationId != 0) {
+ if (mLastNotificationId == icon) {
return;
}
- notificationManager.cancelAsUser(null, mTetheredNotification.icon,
+ notificationManager.cancelAsUser(null, mLastNotificationId,
UserHandle.ALL);
+ mLastNotificationId = 0;
}
Intent intent = new Intent();
@@ -470,31 +472,32 @@ public class Tethering extends BaseNetworkObserver {
CharSequence message = r.getText(com.android.internal.R.string.
tethered_notification_message);
- if (mTetheredNotification == null) {
- mTetheredNotification = new Notification();
- mTetheredNotification.when = 0;
- }
- mTetheredNotification.icon = icon;
- mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
- mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mTetheredNotification.tickerText = title;
- mTetheredNotification.visibility = Notification.VISIBILITY_PUBLIC;
- mTetheredNotification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
- mTetheredNotification.category = Notification.CATEGORY_STATUS;
-
- notificationManager.notifyAsUser(null, mTetheredNotification.icon,
- mTetheredNotification, UserHandle.ALL);
+ if (mTetheredNotificationBuilder == null) {
+ mTetheredNotificationBuilder = new Notification.Builder(mContext);
+ mTetheredNotificationBuilder.setWhen(0)
+ .setOngoing(true)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setCategory(Notification.CATEGORY_STATUS);
+ }
+ mTetheredNotificationBuilder.setSmallIcon(icon)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setContentIntent(pi);
+ mLastNotificationId = icon;
+
+ notificationManager.notifyAsUser(null, mLastNotificationId,
+ mTetheredNotificationBuilder.build(), UserHandle.ALL);
}
private void clearTetheredNotification() {
NotificationManager notificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager != null && mTetheredNotification != null) {
- notificationManager.cancelAsUser(null, mTetheredNotification.icon,
+ if (notificationManager != null && mLastNotificationId != 0) {
+ notificationManager.cancelAsUser(null, mLastNotificationId,
UserHandle.ALL);
- mTetheredNotification = null;
+ mLastNotificationId = 0;
}
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 3dc282b..f222dba 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3260,16 +3260,18 @@ public class SyncManager {
R.string.contentServiceTooManyDeletesNotificationDesc);
Context contextForUser = getContextForUser(user);
- Notification notification =
- new Notification(R.drawable.stat_notify_sync_error,
- mContext.getString(R.string.contentServiceSync),
- System.currentTimeMillis());
- notification.color = contextForUser.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- notification.setLatestEventInfo(contextForUser,
- contextForUser.getString(R.string.contentServiceSyncNotificationTitle),
- String.format(tooManyDeletesDescFormat.toString(), authorityName),
- pendingIntent);
+ Notification notification = new Notification.Builder(contextForUser)
+ .setSmallIcon(R.drawable.stat_notify_sync_error)
+ .setTicker(mContext.getString(R.string.contentServiceSync))
+ .setWhen(System.currentTimeMillis())
+ .setColor(contextForUser.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(contextForUser.getString(
+ R.string.contentServiceSyncNotificationTitle))
+ .setContentText(
+ String.format(tooManyDeletesDescFormat.toString(), authorityName))
+ .setContentIntent(pendingIntent)
+ .build();
notification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotificationMgr.notifyAsUser(null, account.hashCode() ^ authority.hashCode(),
notification, user);
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 7e66cd1..7b1ac5c 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import android.app.AlarmManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
@@ -34,6 +35,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class BackgroundDexOptService extends JobService {
static final String TAG = "BackgroundDexOptService";
+ static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+
static final int BACKGROUND_DEXOPT_JOB = 800;
private static ComponentName sDexoptServiceName = new ComponentName(
"android",
@@ -46,11 +49,12 @@ public class BackgroundDexOptService extends JobService {
final AtomicBoolean mIdleTime = new AtomicBoolean(false);
- public static void schedule(Context context) {
+ public static void schedule(Context context, long minLatency) {
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo job = new JobInfo.Builder(BACKGROUND_DEXOPT_JOB, sDexoptServiceName)
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
+ .setMinimumLatency(minLatency)
.build();
js.schedule(job);
}
@@ -62,6 +66,7 @@ public class BackgroundDexOptService extends JobService {
(PackageManagerService)ServiceManager.getService("package");
if (pm.isStorageLow()) {
+ schedule(BackgroundDexOptService.this, RETRY_LATENCY);
return false;
}
final ArraySet<String> pkgs = pm.getPackagesThatNeedDexOpt();
@@ -77,7 +82,7 @@ public class BackgroundDexOptService extends JobService {
for (String pkg : pkgs) {
if (!mIdleTime.get()) {
// stopped while still working, so we need to reschedule
- schedule(BackgroundDexOptService.this);
+ schedule(BackgroundDexOptService.this, 0);
return;
}
if (sFailedPackageNames.contains(pkg)) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 925a609..29c65db 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -958,7 +958,7 @@ public final class SystemServer {
try {
Slog.i(TAG, "BackgroundDexOptService");
- BackgroundDexOptService.schedule(context);
+ BackgroundDexOptService.schedule(context, 0);
} catch (Throwable e) {
reportWtf("starting BackgroundDexOptService", e);
}
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index c105491..dae7cc5 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -76,5 +76,6 @@
android:authorities="com.google.android.test.activity.single_user"
android:singleUser="true" android:exported="true" />
<receiver android:name="TrackTimeReceiver" />
+ <receiver android:name="AlarmSpamReceiver" />
</application>
</manifest>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index ddcfd9e..94cbabf 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -22,6 +22,7 @@ import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
@@ -36,6 +37,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.graphics.Bitmap;
@@ -58,6 +60,7 @@ public class ActivityTestMain extends Activity {
static final String KEY_CONFIGURATION = "configuration";
ActivityManager mAm;
+ AlarmManager mAlarm;
Configuration mOverrideConfig;
int mSecondUser;
@@ -66,6 +69,7 @@ public class ActivityTestMain extends Activity {
ServiceConnection mIsolatedConnection;
static final int MSG_SPAM = 1;
+ static final int MSG_SPAM_ALARM = 2;
final Handler mHandler = new Handler() {
@Override
@@ -82,6 +86,15 @@ public class ActivityTestMain extends Activity {
startActivity(intent, options);
scheduleSpam(!fg);
} break;
+ case MSG_SPAM_ALARM: {
+ long when = SystemClock.elapsedRealtime();
+ Intent intent = new Intent(ActivityTestMain.this, AlarmSpamReceiver.class);
+ intent.setAction("com.example.SPAM_ALARM=" + when);
+ PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this,
+ 0, intent, 0);
+ mAlarm.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, when+(30*1000), pi);
+ scheduleSpamAlarm(30*1000);
+ } break;
}
super.handleMessage(msg);
}
@@ -146,6 +159,7 @@ public class ActivityTestMain extends Activity {
Log.i(TAG, "Referrer: " + getReferrer());
mAm = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
+ mAlarm = (AlarmManager)getSystemService(ALARM_SERVICE);
if (savedInstanceState != null) {
mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
if (mOverrideConfig != null) {
@@ -436,6 +450,13 @@ public class ActivityTestMain extends Activity {
return true;
}
});
+ menu.add("Spam idle alarm").setOnMenuItemClickListener(
+ new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ scheduleSpamAlarm(0);
+ return true;
+ }
+ });
return true;
}
@@ -467,6 +488,7 @@ public class ActivityTestMain extends Activity {
@Override
protected void onStop() {
super.onStop();
+ mHandler.removeMessages(MSG_SPAM_ALARM);
for (ServiceConnection conn : mConnections) {
unbindService(conn);
}
@@ -536,6 +558,12 @@ public class ActivityTestMain extends Activity {
mHandler.sendMessageDelayed(msg, 500);
}
+ void scheduleSpamAlarm(long delay) {
+ mHandler.removeMessages(MSG_SPAM_ALARM);
+ Message msg = mHandler.obtainMessage(MSG_SPAM_ALARM);
+ mHandler.sendMessageDelayed(msg, delay);
+ }
+
private View scrollWrap(View view) {
ScrollView scroller = new ScrollView(this);
scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java b/tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java
new file mode 100644
index 0000000..0cb1ffb
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class AlarmSpamReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i("AlarmSpamReceiver", "Received spam = " + intent);
+ }
+}
diff --git a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
index 947ea78..2e51570 100644
--- a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
+++ b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
@@ -109,14 +109,20 @@ public class FixVibrateSetting extends Activity implements View.OnClickListener
}
private void test() {
- Notification n = new Notification(R.drawable.stat_sys_warning, "Test notification",
- System.currentTimeMillis());
Intent intent = new Intent(this, FixVibrateSetting.class);
PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
- n.setLatestEventInfo(this, "Test notification", "Test notification", pending);
- n.vibrate = new long[] { 0, 700, 500, 1000 };
- n.flags |= Notification.FLAG_AUTO_CANCEL;
+ Notification n = new Notification.Builder(this)
+ .setSmallIcon(R.drawable.stat_sys_warning)
+ .setTicker("Test notification")
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Test notification")
+ .setContentText("Test notification")
+ .setContentIntent(pending)
+ .setVibrate(new long[] { 0, 700, 500, 1000 })
+ .setAutoCancel(true)
+ .build();
+
mNotificationManager.notify(1, n);
}
}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
index 7691e64..fc3f390 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
@@ -26,15 +26,18 @@ public class SchedulerService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Notification status = new Notification(R.drawable.stat_happy, null,
- System.currentTimeMillis());
- status.flags |= Notification.FLAG_ONGOING_EVENT;
- status.setLatestEventInfo(this, "Scheduler Test running",
- "Scheduler Test running", PendingIntent.getActivity(this, 0,
- new Intent(this, FrameworkPerfActivity.class)
- .setAction(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_LAUNCHER)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0));
+ Notification status = new Notification.Builder(this)
+ .setSmallIcon(R.drawable.stat_happy)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Scheduler Test running")
+ .setContentText("Scheduler Test running")
+ .setContentIntent(PendingIntent.getActivity(this, 0,
+ new Intent(this, FrameworkPerfActivity.class)
+ .setAction(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
+ .setOngoing(true)
+ .build();
startForeground(1, status);
return START_STICKY;
}
diff --git a/tests/StatusBar/res/drawable-hdpi/stat_sys_warning.png b/tests/StatusBar/res/drawable-hdpi/stat_sys_warning.png
new file mode 100644
index 0000000..dbaf944
--- /dev/null
+++ b/tests/StatusBar/res/drawable-hdpi/stat_sys_warning.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/stat_sys_warning.png b/tests/StatusBar/res/drawable-mdpi/stat_sys_warning.png
new file mode 100644
index 0000000..168f8f6
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/stat_sys_warning.png
Binary files differ
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index ba160b1..67b9d77 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -25,7 +25,6 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Vibrator;
import android.os.Handler;
import android.os.UserHandle;
@@ -85,7 +84,7 @@ public class NotificationTestList extends TestActivity
}
private Test[] mTests = new Test[] {
- new Test("Off and sound") {
+ new Test("Off") {
public void run() {
PowerManager pm = (PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl =
@@ -94,9 +93,12 @@ public class NotificationTestList extends TestActivity
pm.goToSleep(SystemClock.uptimeMillis());
- Notification n = new Notification();
- n.sound = Uri.parse("file://" + Environment.getExternalStorageDirectory() +
- "/virtual-void.mp3");
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.stat_sys_phone)
+ .setContentTitle(name)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .build();
Log.d(TAG, "n.sound=" + n.sound);
mNM.notify(1, n);
@@ -114,122 +116,120 @@ public class NotificationTestList extends TestActivity
}
},
- new Test("Button") {
+ new Test("Custom Button") {
public void run() {
- Notification n = new Notification(R.drawable.icon1, null,
- mActivityCreateTime);
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setOngoing(true)
+ .build();
n.contentView = new RemoteViews(getPackageName(), R.layout.button_notification);
- n.flags |= Notification.FLAG_ONGOING_EVENT;
- n.contentIntent = makeIntent();
n.contentView.setOnClickPendingIntent(R.id.button, makeIntent2());
mNM.notify(1, n);
}
},
- new Test("custom intent on text view") {
+ new Test("Action Button") {
public void run() {
- Notification n = new Notification(R.drawable.icon1, null,
- mActivityCreateTime);
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is a notification!!!", null);
- n.contentView.setOnClickPendingIntent(com.android.internal.R.id.text,
- makeIntent2());
- mNM.notify(1, n);
- }
- },
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setOngoing(true)
+ .addAction(R.drawable.ic_statusbar_chat, "Button", makeIntent2())
+ .build();
- new Test("Ticker 1 line") {
- public void run() {
- Notification n = new Notification(R.drawable.icon1, "tick tick tick",
- mActivityCreateTime);
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is a notification!!!", makeIntent());
mNM.notify(1, n);
}
},
- new Test("No view") {
+ new Test("with intent") {
public void run() {
- Notification n = new Notification(R.drawable.icon1, "No view",
- System.currentTimeMillis());
- mNM.notify(1, n);
- }
- },
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle("Persistent #1")
+ .setContentText("This is a notification!!!")
+ .setContentIntent(makeIntent2())
+ .setOngoing(true)
+ .build();
- new Test("No intent") {
- public void run() {
- Notification n = new Notification(R.drawable.icon1, "No intent",
- System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "No intent",
- "No intent", null);
mNM.notify(1, n);
}
},
- new Test("Layout") {
+ new Test("Whens") {
public void run()
{
- Notification n;
+ Notification.Builder n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setContentTitle(name)
+ .setOngoing(true);
- n = new Notification(NotificationTestList.this,
- R.drawable.ic_statusbar_missedcall,
- null, System.currentTimeMillis()-(1000*60*60*24),
- "(453) 123-2328",
- "", null);
- n.flags |= Notification.FLAG_ONGOING_EVENT;
+ mNM.notify(1, n.setContentTitle("(453) 123-2328")
+ .setWhen(System.currentTimeMillis()-(1000*60*60*24))
+ .build());
- mNM.notify(1, n);
-
- mNM.notify(2, new Notification(NotificationTestList.this,
- R.drawable.ic_statusbar_email,
- null, System.currentTimeMillis(),
- "Mark Willem, Me (2)",
- "Re: Didn't you get the memo?", null));
+ mNM.notify(1, n.setContentTitle("Mark Willem, Me (2)")
+ .setWhen(System.currentTimeMillis())
+ .build());
- mNM.notify(3, new Notification(NotificationTestList.this,
- R.drawable.ic_statusbar_chat,
- null, System.currentTimeMillis()+(1000*60*60*24),
- "Sophia Winterlanden",
- "Lorem ipsum dolor sit amet.", null));
+ mNM.notify(1, n.setContentTitle("Sophia Winterlanden")
+ .setWhen(System.currentTimeMillis() + (1000 * 60 * 60 * 24))
+ .build());
}
},
new Test("Bad Icon #1 (when=create)") {
public void run() {
- Notification n = new Notification(R.layout.chrono_notification /* not an icon */,
- null, mActivityCreateTime);
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is the same notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.layout.chrono_notification /* not an icon */)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle("Persistent #1")
+ .setContentText("This is the same notification!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(1, n);
}
},
new Test("Bad Icon #1 (when=now)") {
public void run() {
- Notification n = new Notification(R.layout.chrono_notification /* not an icon */,
- null, System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is the same notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.layout.chrono_notification /* not an icon */)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Persistent #1")
+ .setContentText("This is the same notification!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(1, n);
}
},
new Test("Null Icon #1 (when=now)") {
public void run() {
- Notification n = new Notification(0, null, System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is the same notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(0)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Persistent #1")
+ .setContentText("This is the same notification!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(1, n);
}
},
new Test("Bad resource #1 (when=create)") {
public void run() {
- Notification n = new Notification(R.drawable.icon2,
- null, mActivityCreateTime);
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is the same notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle("Persistent #1")
+ .setContentText("This is the same notification!!")
+ .setContentIntent(makeIntent())
+ .build();
n.contentView.setInt(1 /*bogus*/, "bogus method", 666);
mNM.notify(1, n);
}
@@ -237,29 +237,18 @@ public class NotificationTestList extends TestActivity
new Test("Bad resource #1 (when=now)") {
public void run() {
- Notification n = new Notification(R.drawable.icon2,
- null, System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is the same notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Persistent #1")
+ .setContentText("This is the same notification!!")
+ .setContentIntent(makeIntent())
+ .build();
n.contentView.setInt(1 /*bogus*/, "bogus method", 666);
mNM.notify(1, n);
}
},
-
- new Test("Bad resource #3") {
- public void run()
- {
- Notification n = new Notification(NotificationTestList.this,
- R.drawable.ic_statusbar_missedcall,
- null, System.currentTimeMillis()-(1000*60*60*24),
- "(453) 123-2328",
- "", null);
- n.contentView.setInt(1 /*bogus*/, "bogus method", 666);
- mNM.notify(3, n);
- }
- },
-
new Test("Times") {
public void run()
{
@@ -278,22 +267,25 @@ public class NotificationTestList extends TestActivity
new Runnable() {
public void run() {
Log.d(TAG, "Stress - Ongoing/Latest 0");
- Notification n = new Notification(NotificationTestList.this,
- R.drawable.icon3,
- null, System.currentTimeMillis(), "Stress - Ongoing",
- "Notify me!!!", null);
- n.flags |= Notification.FLAG_ONGOING_EVENT;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon3)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Stress - Ongoing")
+ .setContentText("Notify me!!!")
+ .setOngoing(true)
+ .build();
mNM.notify(1, n);
}
},
new Runnable() {
public void run() {
Log.d(TAG, "Stress - Ongoing/Latest 1");
- Notification n = new Notification(NotificationTestList.this,
- R.drawable.icon4,
- null, System.currentTimeMillis(), "Stress - Latest",
- "Notify me!!!", null);
- //n.flags |= Notification.FLAG_ONGOING_EVENT;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon4)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Stress - Latest")
+ .setContentText("Notify me!!!")
+ .build();
mNM.notify(1, n);
}
}
@@ -302,12 +294,15 @@ public class NotificationTestList extends TestActivity
new Test("Long") {
public void run()
{
- Notification n = new Notification();
- n.defaults |= Notification.DEFAULT_SOUND ;
- n.vibrate = new long[] {
- 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
- 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
- 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setContentTitle(name)
+ .setDefaults(Notification.DEFAULT_SOUND)
+ .setVibrate(new long[] {
+ 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+ 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+ 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 })
+ .build();
mNM.notify(1, n);
}
},
@@ -320,21 +315,19 @@ public class NotificationTestList extends TestActivity
Thread t = new Thread() {
public void run() {
int x = 0;
+ final Notification.Builder n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setContentTitle(name)
+ .setOngoing(true);
+
while (!mProgressDone) {
- Notification n = new Notification(R.drawable.icon1, null,
- PROGRESS_UPDATES_WHEN
+ n.setWhen(PROGRESS_UPDATES_WHEN
? System.currentTimeMillis()
: mActivityCreateTime);
- RemoteViews v = new RemoteViews(getPackageName(),
- R.layout.progress_notification);
-
- v.setProgressBar(R.id.progress_bar, 100, x, false);
- v.setTextViewText(R.id.status_text, "Progress: " + x + "%");
-
- n.contentView = v;
- n.flags |= Notification.FLAG_ONGOING_EVENT;
-
- mNM.notify(500, n);
+ n.setProgress(100, x, false);
+ n.setContentText("Progress: " + x + "%");
+
+ mNM.notify(500, n.build());
x = (x + 7) % 100;
try {
@@ -359,11 +352,12 @@ public class NotificationTestList extends TestActivity
new Test("Blue Lights") {
public void run()
{
- Notification n = new Notification();
- n.flags |= Notification.FLAG_SHOW_LIGHTS;
- n.ledARGB = 0xff0000ff;
- n.ledOnMS = 1;
- n.ledOffMS = 0;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setLights(0xff0000ff, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .build();
mNM.notify(1, n);
}
},
@@ -371,11 +365,12 @@ public class NotificationTestList extends TestActivity
new Test("Red Lights") {
public void run()
{
- Notification n = new Notification();
- n.flags |= Notification.FLAG_SHOW_LIGHTS;
- n.ledARGB = 0xffff0000;
- n.ledOnMS = 1;
- n.ledOffMS = 0;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setLights(0xffff0000, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .build();
mNM.notify(1, n);
}
},
@@ -383,11 +378,12 @@ public class NotificationTestList extends TestActivity
new Test("Yellow Lights") {
public void run()
{
- Notification n = new Notification();
- n.flags |= Notification.FLAG_SHOW_LIGHTS;
- n.ledARGB = 0xffffff00;
- n.ledOnMS = 1;
- n.ledOffMS = 0;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setLights(0xffffff00, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .build();
mNM.notify(1, n);
}
},
@@ -395,11 +391,12 @@ public class NotificationTestList extends TestActivity
new Test("Lights off") {
public void run()
{
- Notification n = new Notification();
- n.flags |= Notification.FLAG_SHOW_LIGHTS;
- n.ledARGB = 0x00000000;
- n.ledOnMS = 0;
- n.ledOffMS = 0;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setLights(0x00000000, 0, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .build();
mNM.notify(1, n);
}
},
@@ -407,11 +404,12 @@ public class NotificationTestList extends TestActivity
new Test("Blue Blinking Slow") {
public void run()
{
- Notification n = new Notification();
- n.flags |= Notification.FLAG_SHOW_LIGHTS;
- n.ledARGB = 0xff0000ff;
- n.ledOnMS = 1300;
- n.ledOffMS = 1300;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setLights(0xff0000ff, 1300, 1300)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .build();
mNM.notify(1, n);
}
},
@@ -419,11 +417,12 @@ public class NotificationTestList extends TestActivity
new Test("Blue Blinking Fast") {
public void run()
{
- Notification n = new Notification();
- n.flags |= Notification.FLAG_SHOW_LIGHTS;
- n.ledARGB = 0xff0000ff;
- n.ledOnMS = 300;
- n.ledOffMS = 300;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setLights(0xff0000ff, 300, 300)
+ .setDefaults(Notification.DEFAULT_LIGHTS)
+ .build();
mNM.notify(1, n);
}
},
@@ -431,8 +430,11 @@ public class NotificationTestList extends TestActivity
new Test("Default All") {
public void run()
{
- Notification n = new Notification();
- n.defaults |= Notification.DEFAULT_ALL;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .build();
mNM.notify(1, n);
}
},
@@ -440,20 +442,12 @@ public class NotificationTestList extends TestActivity
new Test("Default All, once") {
public void run()
{
- Notification n = new Notification();
- n.defaults |= Notification.DEFAULT_ALL;
- n.flags |= Notification.FLAG_ONLY_ALERT_ONCE ;
- mNM.notify(1, n);
- }
- },
-
- new Test("Content Sound") {
- public void run()
- {
- Notification n = new Notification();
- n.sound = Uri.parse(
- "content://media/internal/audio/media/7");
-
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle(name)
+ .setOnlyAlertOnce(true)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .build();
mNM.notify(1, n);
}
},
@@ -461,10 +455,12 @@ public class NotificationTestList extends TestActivity
new Test("Resource Sound") {
public void run()
{
- Notification n = new Notification();
- n.sound = Uri.parse(
- ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
- getPackageName() + "/raw/ringer");
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.stat_sys_phone)
+ .setContentTitle(name)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .build();
Log.d(TAG, "n.sound=" + n.sound);
mNM.notify(1, n);
@@ -474,9 +470,13 @@ public class NotificationTestList extends TestActivity
new Test("Sound and Cancel") {
public void run()
{
- Notification n = new Notification();
- n.sound = Uri.parse(
- "content://media/internal/audio/media/7");
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.stat_sys_phone)
+ .setContentTitle(name)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .build();
+ Log.d(TAG, "n.sound=" + n.sound);
mNM.notify(1, n);
SystemClock.sleep(200);
@@ -487,8 +487,11 @@ public class NotificationTestList extends TestActivity
new Test("Vibrate") {
public void run()
{
- Notification n = new Notification();
- n.vibrate = new long[] { 0, 700, 500, 1000 };
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.stat_sys_phone)
+ .setContentTitle(name)
+ .setVibrate(new long[]{0, 700, 500, 1000})
+ .build();
mNM.notify(1, n);
}
@@ -497,8 +500,11 @@ public class NotificationTestList extends TestActivity
new Test("Vibrate and cancel") {
public void run()
{
- Notification n = new Notification();
- n.vibrate = new long[] { 0, 700, 500, 1000 };
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.stat_sys_phone)
+ .setContentTitle(name)
+ .setVibrate(new long[]{0, 700, 500, 1000})
+ .build();
mNM.notify(1, n);
SystemClock.sleep(500);
@@ -566,10 +572,13 @@ public class NotificationTestList extends TestActivity
new Test("Persistent #1") {
public void run() {
- Notification n = new Notification(R.drawable.icon1, "tick tick tick",
- mActivityCreateTime);
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is a notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setContentText("This is a notification!!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(1, n);
}
},
@@ -578,18 +587,19 @@ public class NotificationTestList extends TestActivity
public void run() {
mHandler.postDelayed(new Runnable() {
public void run() {
- Notification n = new Notification(R.drawable.icon1,
- " "
+ String message = " "
+ "tick tock tick tock\n\nSometimes notifications can "
+ "be really long and wrap to more than one line.\n"
+ "Sometimes."
+ "Ohandwhathappensifwehaveonereallylongstringarewesure"
- + "thatwesegmentitcorrectly?\n",
- System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this,
- "Still Persistent #1",
- "This is still a notification!!!",
- makeIntent());
+ + "thatwesegmentitcorrectly?\n";
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setContentTitle(name)
+ .setContentText("This is still a notification!!!")
+ .setContentIntent(makeIntent())
+ .setStyle(new Notification.BigTextStyle().bigText(message))
+ .build();
mNM.notify(1, n);
}
}, 3000);
@@ -598,54 +608,67 @@ public class NotificationTestList extends TestActivity
new Test("Persistent #2") {
public void run() {
- Notification n = new Notification(R.drawable.icon2, "tock tock tock",
- System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #2",
- "Notify me!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setContentText("This is a notification!!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(2, n);
}
},
new Test("Persistent #3") {
public void run() {
- Notification n = new Notification(R.drawable.icon2, "tock tock tock\nmooooo",
- System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #3",
- "Notify me!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setContentText("This is a notification!!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(3, n);
}
},
new Test("Persistent #2 Vibrate") {
public void run() {
- Notification n = new Notification(R.drawable.icon2, "tock tock tock",
- System.currentTimeMillis());
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #2",
- "Notify me!!!", makeIntent());
- n.defaults = Notification.DEFAULT_VIBRATE;
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setContentText("This is a notification!!!")
+ .setContentIntent(makeIntent())
+ .setDefaults(Notification.DEFAULT_VIBRATE)
+ .build();
mNM.notify(2, n);
}
},
new Test("Persistent #1 - different icon") {
public void run() {
- Notification n = new Notification(R.drawable.icon2, null,
- mActivityCreateTime);
- n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
- "This is the same notification!!!", makeIntent());
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle(name)
+ .setContentText("This is a notification!!!")
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(1, n);
}
},
new Test("Chronometer Start") {
public void run() {
- Notification n = new Notification(R.drawable.icon2, "me me me me",
- System.currentTimeMillis());
- n.contentView = new RemoteViews(getPackageName(), R.layout.chrono_notification);
- mChronometerBase = SystemClock.elapsedRealtime();
- n.contentView.setChronometer(R.id.time, mChronometerBase, "Yay! (%s)", true);
- n.flags |= Notification.FLAG_ONGOING_EVENT;
- n.contentIntent = makeIntent();
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle(name)
+ .setContentIntent(makeIntent())
+ .setOngoing(true)
+ .setUsesChronometer(true)
+ .build();
mNM.notify(2, n);
}
},
@@ -655,12 +678,12 @@ public class NotificationTestList extends TestActivity
mHandler.postDelayed(new Runnable() {
public void run() {
Log.d(TAG, "Chronometer Stop");
- Notification n = new Notification();
- n.icon = R.drawable.icon1;
- n.contentView = new RemoteViews(getPackageName(),
- R.layout.chrono_notification);
- n.contentView.setChronometer(R.id.time, mChronometerBase, null, false);
- n.contentIntent = makeIntent();
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle(name)
+ .setContentIntent(makeIntent())
+ .build();
mNM.notify(2, n);
}
}, 3000);
@@ -669,29 +692,29 @@ public class NotificationTestList extends TestActivity
new Test("Sequential Persistent") {
public void run() {
- mNM.notify(1, notificationWithNumbers(1));
- mNM.notify(2, notificationWithNumbers(2));
+ mNM.notify(1, notificationWithNumbers(name, 1));
+ mNM.notify(2, notificationWithNumbers(name, 2));
}
},
new Test("Replace Persistent") {
public void run() {
- mNM.notify(1, notificationWithNumbers(1));
- mNM.notify(1, notificationWithNumbers(1));
+ mNM.notify(1, notificationWithNumbers(name, 1));
+ mNM.notify(1, notificationWithNumbers(name, 1));
}
},
new Test("Run and Cancel (n=1)") {
public void run() {
- mNM.notify(1, notificationWithNumbers(1));
+ mNM.notify(1, notificationWithNumbers(name, 1));
mNM.cancel(1);
}
},
new Test("Run an Cancel (n=2)") {
public void run() {
- mNM.notify(1, notificationWithNumbers(1));
- mNM.notify(2, notificationWithNumbers(2));
+ mNM.notify(1, notificationWithNumbers(name, 1));
+ mNM.notify(2, notificationWithNumbers(name, 2));
mNM.cancel(2);
}
},
@@ -701,8 +724,8 @@ public class NotificationTestList extends TestActivity
public void run() {
for (int i = 0; i < 10; i++) {
Log.d(TAG, "Add two notifications");
- mNM.notify(1, notificationWithNumbers(1));
- mNM.notify(2, notificationWithNumbers(2));
+ mNM.notify(1, notificationWithNumbers(name, 1));
+ mNM.notify(2, notificationWithNumbers(name, 2));
Log.d(TAG, "Cancel two notifications");
mNM.cancel(1);
mNM.cancel(2);
@@ -712,29 +735,14 @@ public class NotificationTestList extends TestActivity
new Test("Ten Notifications") {
public void run() {
- for (int i = 0; i < 2; i++) {
- Notification n = new Notification(
- kNumberedIconResIDs[i],
- null, System.currentTimeMillis());
- n.number = i;
- n.setLatestEventInfo(
- NotificationTestList.this,
- "Persistent #" + i,
- "Notify me!!!" + i,
- null);
- n.flags |= Notification.FLAG_ONGOING_EVENT;
- mNM.notify((i+1)*10, n);
- }
- for (int i = 2; i < 10; i++) {
- Notification n = new Notification(
- kNumberedIconResIDs[i],
- null, System.currentTimeMillis());
- n.number = i;
- n.setLatestEventInfo(
- NotificationTestList.this,
- "Persistent #" + i,
- "Notify me!!!" + i,
- null);
+ for (int i = 0; i < 10; i++) {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(kNumberedIconResIDs[i])
+ .setContentTitle("Persistent #" + i)
+ .setContentText("Notify me!!!" + i)
+ .setOngoing(i < 2)
+ .setNumber(i)
+ .build();
mNM.notify((i+1)*10, n);
}
}
@@ -757,25 +765,25 @@ public class NotificationTestList extends TestActivity
new Test("Persistent with numbers 1") {
public void run() {
- mNM.notify(1, notificationWithNumbers(1));
+ mNM.notify(1, notificationWithNumbers(name, 1));
}
},
new Test("Persistent with numbers 22") {
public void run() {
- mNM.notify(1, notificationWithNumbers(22));
+ mNM.notify(1, notificationWithNumbers(name, 22));
}
},
new Test("Persistent with numbers 333") {
public void run() {
- mNM.notify(1, notificationWithNumbers(333));
+ mNM.notify(1, notificationWithNumbers(name, 333));
}
},
new Test("Persistent with numbers 4444") {
public void run() {
- mNM.notify(1, notificationWithNumbers(4444));
+ mNM.notify(1, notificationWithNumbers(name, 4444));
}
},
@@ -786,7 +794,7 @@ public class NotificationTestList extends TestActivity
.setContentTitle("High priority")
.setContentText("This should appear before all others")
.setPriority(Notification.PRIORITY_HIGH)
- .getNotification();
+ .build();
int[] idOut = new int[1];
try {
@@ -812,7 +820,7 @@ public class NotificationTestList extends TestActivity
.setContentTitle("MAX priority")
.setContentText("This might appear as an intruder alert")
.setPriority(Notification.PRIORITY_MAX)
- .getNotification();
+ .build();
int[] idOut = new int[1];
try {
@@ -838,7 +846,7 @@ public class NotificationTestList extends TestActivity
.setContentTitle("MIN priority")
.setContentText("You should not see this")
.setPriority(Notification.PRIORITY_MIN)
- .getNotification();
+ .build();
int[] idOut = new int[1];
try {
@@ -875,16 +883,15 @@ public class NotificationTestList extends TestActivity
};
- private Notification notificationWithNumbers(int num) {
- Notification n = new Notification(this,
- (num >= 0 && num < kNumberedIconResIDs.length)
- ? kNumberedIconResIDs[num]
- : kUnnumberedIconResID,
- null,
- System.currentTimeMillis(),
- "Notification", "Number=" + num,
- null);
- n.number = num;
+ private Notification notificationWithNumbers(String name, int num) {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon((num >= 0 && num < kNumberedIconResIDs.length)
+ ? kNumberedIconResIDs[num]
+ : kUnnumberedIconResID)
+ .setContentTitle(name)
+ .setContentText("Number=" + num)
+ .setNumber(num)
+ .build();
return n;
}
@@ -932,9 +939,12 @@ public class NotificationTestList extends TestActivity
}
void timeNotification(int n, String label, long time) {
- mNM.notify(n, new Notification(NotificationTestList.this,
- R.drawable.ic_statusbar_missedcall, null,
- time, label, "" + new java.util.Date(time), null));
+ mNM.notify(n, new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.ic_statusbar_missedcall)
+ .setWhen(time)
+ .setContentTitle(label)
+ .setContentText(new java.util.Date(time).toString())
+ .build());
}
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 50f98b8..cd04c2e 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -153,25 +153,24 @@ public class StatusBarTest extends TestActivity
},
new Test("Priority notification") {
public void run() {
- Notification not = new Notification();
- not.icon = R.drawable.stat_sys_phone;
- not.when = System.currentTimeMillis()-(1000*60*60*24);
- not.setLatestEventInfo(StatusBarTest.this,
- "Incoming call",
- "from: Imperious Leader",
- null
- );
- not.flags |= Notification.FLAG_HIGH_PRIORITY;
Intent fullScreenIntent = new Intent(StatusBarTest.this, TestAlertActivity.class);
int id = (int)System.currentTimeMillis(); // XXX HAX
fullScreenIntent.putExtra("id", id);
- not.fullScreenIntent = PendingIntent.getActivity(
+ PendingIntent pi = PendingIntent.getActivity(
StatusBarTest.this,
0,
fullScreenIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
- // if you tap on it you should get the original alert box
- not.contentIntent = not.fullScreenIntent;
+ Notification not = new Notification.Builder(StatusBarTest.this)
+ .setSmallIcon(R.drawable.stat_sys_phone)
+ .setWhen(System.currentTimeMillis() - (1000 * 60 * 60 * 24))
+ .setContentTitle("Incoming call")
+ .setContentText("from: Imperious Leader")
+ .setContentIntent(pi)
+ .setFullScreenIntent(pi, true)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .build();
+
mNotificationManager.notify(id, not);
}
},