Merge "MidiManager: Address API Council feedback:" into mnc-dev
diff --git a/Android.mk b/Android.mk
index 264ad48..307709a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -519,10 +519,11 @@
 	frameworks/base/core/java/android/net/Uri.aidl \
 	frameworks/base/core/java/android/net/NetworkRequest.aidl \
 	frameworks/base/core/java/android/net/LinkAddress.aidl \
-	frameworks/base/core/java/android/view/Surface.aidl \
-	frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
+	frameworks/base/core/java/android/view/Display.aidl \
 	frameworks/base/core/java/android/view/InputDevice.aidl \
 	frameworks/base/core/java/android/view/InputEvent.aidl \
+	frameworks/base/core/java/android/view/Surface.aidl \
+	frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
 	frameworks/base/core/java/android/view/inputmethod/InputMethodSubtype.aidl \
 	frameworks/base/core/java/android/view/inputmethod/CursorAnchorInfo.aidl \
 	frameworks/base/core/java/android/view/inputmethod/CompletionInfo.aidl \
diff --git a/api/current.txt b/api/current.txt
index 827d9b7..06fb46e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7759,7 +7759,7 @@
     field public static final java.lang.String MIDI_SERVICE = "midi";
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
-    field public static final int MODE_MULTI_PROCESS = 4; // 0x4
+    field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -18091,7 +18091,7 @@
     method public void ignoreNetworkWithCaptivePortal(android.net.Network, java.lang.String);
     method public boolean isActiveNetworkMetered();
     method public boolean isDefaultNetworkActive();
-    method public static boolean isNetworkTypeValid(int);
+    method public static deprecated boolean isNetworkTypeValid(int);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void releaseNetworkRequest(android.app.PendingIntent);
     method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
@@ -27734,7 +27734,7 @@
     method public final android.content.Context getApplicationContext();
     method public android.renderscript.RenderScript.RSErrorHandler getErrorHandler();
     method public android.renderscript.RenderScript.RSMessageHandler getMessageHandler();
-    method public static long getMinorID();
+    method public static long getMinorVersion();
     method public static void releaseAllContexts();
     method public void sendMessage(int, int[]);
     method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
@@ -28308,6 +28308,9 @@
     method public java.lang.String getKemKdfAlgorithm();
     method public int getKemPointFormat();
     field public static final android.security.EcIesParameterSpec DEFAULT;
+    field public static final int POINT_FORMAT_COMPRESSED = 1; // 0x1
+    field public static final int POINT_FORMAT_UNCOMPRESSED = 0; // 0x0
+    field public static final int POINT_FORMAT_UNSPECIFIED = -1; // 0xffffffff
   }
 
   public static class EcIesParameterSpec.Builder {
@@ -28321,15 +28324,6 @@
     method public android.security.EcIesParameterSpec.Builder setKemPointFormat(int);
   }
 
-  public static abstract class EcIesParameterSpec.PointFormat {
-    field public static final int COMPRESSED = 1; // 0x1
-    field public static final int UNCOMPRESSED = 0; // 0x0
-    field public static final int UNSPECIFIED = -1; // 0xffffffff
-  }
-
-  public static abstract class EcIesParameterSpec.PointFormatEnum implements java.lang.annotation.Annotation {
-  }
-
   public final class KeyChain {
     ctor public KeyChain();
     method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -28459,80 +28453,38 @@
   }
 
   public abstract class KeyStoreKeyProperties {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Algorithm {
-    field public static final java.lang.String AES = "AES";
-    field public static final java.lang.String EC = "EC";
-    field public static final java.lang.String HMAC_SHA1 = "HmacSHA1";
-    field public static final java.lang.String HMAC_SHA224 = "HmacSHA224";
-    field public static final java.lang.String HMAC_SHA256 = "HmacSHA256";
-    field public static final java.lang.String HMAC_SHA384 = "HmacSHA384";
-    field public static final java.lang.String HMAC_SHA512 = "HmacSHA512";
-    field public static final java.lang.String RSA = "RSA";
-  }
-
-  public static abstract class KeyStoreKeyProperties.AlgorithmEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.BlockMode {
-    field public static final java.lang.String CBC = "CBC";
-    field public static final java.lang.String CTR = "CTR";
-    field public static final java.lang.String ECB = "ECB";
-    field public static final java.lang.String GCM = "GCM";
-  }
-
-  public static abstract class KeyStoreKeyProperties.BlockModeEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Digest {
-    field public static final java.lang.String MD5 = "MD5";
-    field public static final java.lang.String NONE = "NONE";
-    field public static final java.lang.String SHA1 = "SHA-1";
-    field public static final java.lang.String SHA224 = "SHA-224";
-    field public static final java.lang.String SHA256 = "SHA-256";
-    field public static final java.lang.String SHA384 = "SHA-384";
-    field public static final java.lang.String SHA512 = "SHA-512";
-  }
-
-  public static abstract class KeyStoreKeyProperties.DigestEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.EncryptionPadding {
-    field public static final java.lang.String NONE = "NoPadding";
-    field public static final java.lang.String PKCS7 = "PKCS7Padding";
-    field public static final java.lang.String RSA_OAEP = "OAEPPadding";
-    field public static final java.lang.String RSA_PKCS1 = "PKCS1Padding";
-  }
-
-  public static abstract class KeyStoreKeyProperties.EncryptionPaddingEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Origin {
-    field public static final int GENERATED = 1; // 0x1
-    field public static final int IMPORTED = 2; // 0x2
-    field public static final int UNKNOWN = 4; // 0x4
-  }
-
-  public static abstract class KeyStoreKeyProperties.OriginEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Purpose {
-    field public static final int DECRYPT = 2; // 0x2
-    field public static final int ENCRYPT = 1; // 0x1
-    field public static final int SIGN = 4; // 0x4
-    field public static final int VERIFY = 8; // 0x8
-  }
-
-  public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.SignaturePadding {
-    field public static final java.lang.String RSA_PKCS1 = "PKCS1";
-    field public static final java.lang.String RSA_PSS = "PSS";
-  }
-
-  public static abstract class KeyStoreKeyProperties.SignaturePaddingEnum implements java.lang.annotation.Annotation {
+    field public static final java.lang.String BLOCK_MODE_CBC = "CBC";
+    field public static final java.lang.String BLOCK_MODE_CTR = "CTR";
+    field public static final java.lang.String BLOCK_MODE_ECB = "ECB";
+    field public static final java.lang.String BLOCK_MODE_GCM = "GCM";
+    field public static final java.lang.String DIGEST_MD5 = "MD5";
+    field public static final java.lang.String DIGEST_NONE = "NONE";
+    field public static final java.lang.String DIGEST_SHA1 = "SHA-1";
+    field public static final java.lang.String DIGEST_SHA224 = "SHA-224";
+    field public static final java.lang.String DIGEST_SHA256 = "SHA-256";
+    field public static final java.lang.String DIGEST_SHA384 = "SHA-384";
+    field public static final java.lang.String DIGEST_SHA512 = "SHA-512";
+    field public static final java.lang.String ENCRYPTION_PADDING_NONE = "NoPadding";
+    field public static final java.lang.String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
+    field public static final java.lang.String ENCRYPTION_PADDING_RSA_OAEP = "OAEPPadding";
+    field public static final java.lang.String ENCRYPTION_PADDING_RSA_PKCS1 = "PKCS1Padding";
+    field public static final java.lang.String KEY_ALGORITHM_AES = "AES";
+    field public static final java.lang.String KEY_ALGORITHM_EC = "EC";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA224 = "HmacSHA224";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA256 = "HmacSHA256";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA384 = "HmacSHA384";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA512 = "HmacSHA512";
+    field public static final java.lang.String KEY_ALGORITHM_RSA = "RSA";
+    field public static final int ORIGIN_GENERATED = 1; // 0x1
+    field public static final int ORIGIN_IMPORTED = 2; // 0x2
+    field public static final int ORIGIN_UNKNOWN = 4; // 0x4
+    field public static final int PURPOSE_DECRYPT = 2; // 0x2
+    field public static final int PURPOSE_ENCRYPT = 1; // 0x1
+    field public static final int PURPOSE_SIGN = 4; // 0x4
+    field public static final int PURPOSE_VERIFY = 8; // 0x8
+    field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
+    field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
 
   public class KeyStoreKeySpec implements java.security.spec.KeySpec {
@@ -30092,27 +30044,17 @@
     field public static final int PROPERTY_WIFI = 8; // 0x8
   }
 
-  public final class CameraCapabilities implements android.os.Parcelable {
-    ctor public CameraCapabilities(int, int);
-    method public int describeContents();
-    method public int getHeight();
-    method public int getWidth();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.telecom.CameraCapabilities> CREATOR;
-  }
-
   public abstract class Conference implements android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
     method public final void destroy();
     method public final android.telecom.AudioState getAudioState();
     method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
-    method public final long getConnectTimeMillis();
     method public final int getConnectionCapabilities();
+    method public final long getConnectionTime();
     method public final java.util.List<android.telecom.Connection> getConnections();
     method public final android.telecom.DisconnectCause getDisconnectCause();
     method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
-    method public android.telecom.Connection getPrimaryConnection();
     method public final int getState();
     method public final android.telecom.StatusHints getStatusHints();
     method public android.telecom.Connection.VideoProvider getVideoProvider();
@@ -30131,8 +30073,8 @@
     method public final void removeConnection(android.telecom.Connection);
     method public final void setActive();
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
-    method public void setConnectTimeMillis(long);
     method public final void setConnectionCapabilities(int);
+    method public final void setConnectionTime(long);
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setOnHold();
     method public final void setStatusHints(android.telecom.StatusHints);
@@ -30227,7 +30169,7 @@
   public static abstract class Connection.VideoProvider {
     ctor public Connection.VideoProvider();
     method public void changeCallDataUsage(long);
-    method public void changeCameraCapabilities(android.telecom.CameraCapabilities);
+    method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
     method public void changePeerDimensions(int, int);
     method public void changeVideoQuality(int);
     method public void handleCallSessionEvent(int);
@@ -30359,14 +30301,14 @@
     ctor public InCallService.VideoCall.Callback();
     method public abstract void onCallDataUsageChanged(long);
     method public abstract void onCallSessionEvent(int);
-    method public abstract void onCameraCapabilitiesChanged(android.telecom.CameraCapabilities);
+    method public abstract void onCameraCapabilitiesChanged(android.telecom.VideoProfile.CameraCapabilities);
     method public abstract void onPeerDimensionsChanged(int, int);
     method public abstract void onSessionModifyRequestReceived(android.telecom.VideoProfile);
     method public abstract void onSessionModifyResponseReceived(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
     method public abstract void onVideoQualityChanged(int);
   }
 
-  public class PhoneAccount implements android.os.Parcelable {
+  public final class PhoneAccount implements android.os.Parcelable {
     method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
     method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
     method public int describeContents();
@@ -30418,7 +30360,7 @@
     method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
   }
 
-  public class PhoneAccountHandle implements android.os.Parcelable {
+  public final class PhoneAccountHandle implements android.os.Parcelable {
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String, android.os.UserHandle);
     method public int describeContents();
@@ -30576,6 +30518,15 @@
     field public static final int QUALITY_MEDIUM = 2; // 0x2
   }
 
+  public static final class VideoProfile.CameraCapabilities implements android.os.Parcelable {
+    ctor public VideoProfile.CameraCapabilities(int, int);
+    method public int describeContents();
+    method public int getHeight();
+    method public int getWidth();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile.CameraCapabilities> CREATOR;
+  }
+
   public static class VideoProfile.VideoState {
     ctor public VideoProfile.VideoState();
     method public static boolean isAudioOnly(int);
@@ -34574,6 +34525,7 @@
     method public int getFlags();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
+    method public android.view.Display.Mode getMode();
     method public java.lang.String getName();
     method public deprecated int getOrientation();
     method public deprecated int getPixelFormat();
@@ -34585,7 +34537,8 @@
     method public int getRotation();
     method public void getSize(android.graphics.Point);
     method public int getState();
-    method public float[] getSupportedRefreshRates();
+    method public android.view.Display.Mode[] getSupportedModes();
+    method public deprecated float[] getSupportedRefreshRates();
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
@@ -34600,6 +34553,16 @@
     field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
+  public static final class Display.Mode implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getModeId();
+    method public int getPhysicalHeight();
+    method public int getPhysicalWidth();
+    method public float getRefreshRate();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR;
+  }
+
   public class DragEvent implements android.os.Parcelable {
     method public int describeContents();
     method public int getAction();
@@ -37390,7 +37353,8 @@
     field public float horizontalWeight;
     field public deprecated int memoryType;
     field public java.lang.String packageName;
-    field public float preferredRefreshRate;
+    field public int preferredDisplayModeId;
+    field public deprecated float preferredRefreshRate;
     field public int rotationAnimation;
     field public float screenBrightness;
     field public int screenOrientation;
diff --git a/api/system-current.txt b/api/system-current.txt
index 6c6b601..e059f1c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7976,7 +7976,7 @@
     field public static final java.lang.String MIDI_SERVICE = "midi";
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
-    field public static final int MODE_MULTI_PROCESS = 4; // 0x4
+    field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -19568,7 +19568,7 @@
     method public void ignoreNetworkWithCaptivePortal(android.net.Network, java.lang.String);
     method public boolean isActiveNetworkMetered();
     method public boolean isDefaultNetworkActive();
-    method public static boolean isNetworkTypeValid(int);
+    method public static deprecated boolean isNetworkTypeValid(int);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void releaseNetworkRequest(android.app.PendingIntent);
     method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
@@ -29757,7 +29757,7 @@
     method public final android.content.Context getApplicationContext();
     method public android.renderscript.RenderScript.RSErrorHandler getErrorHandler();
     method public android.renderscript.RenderScript.RSMessageHandler getMessageHandler();
-    method public static long getMinorID();
+    method public static long getMinorVersion();
     method public static void releaseAllContexts();
     method public void sendMessage(int, int[]);
     method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
@@ -30331,6 +30331,9 @@
     method public java.lang.String getKemKdfAlgorithm();
     method public int getKemPointFormat();
     field public static final android.security.EcIesParameterSpec DEFAULT;
+    field public static final int POINT_FORMAT_COMPRESSED = 1; // 0x1
+    field public static final int POINT_FORMAT_UNCOMPRESSED = 0; // 0x0
+    field public static final int POINT_FORMAT_UNSPECIFIED = -1; // 0xffffffff
   }
 
   public static class EcIesParameterSpec.Builder {
@@ -30344,15 +30347,6 @@
     method public android.security.EcIesParameterSpec.Builder setKemPointFormat(int);
   }
 
-  public static abstract class EcIesParameterSpec.PointFormat {
-    field public static final int COMPRESSED = 1; // 0x1
-    field public static final int UNCOMPRESSED = 0; // 0x0
-    field public static final int UNSPECIFIED = -1; // 0xffffffff
-  }
-
-  public static abstract class EcIesParameterSpec.PointFormatEnum implements java.lang.annotation.Annotation {
-  }
-
   public final class KeyChain {
     ctor public KeyChain();
     method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -30482,80 +30476,38 @@
   }
 
   public abstract class KeyStoreKeyProperties {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Algorithm {
-    field public static final java.lang.String AES = "AES";
-    field public static final java.lang.String EC = "EC";
-    field public static final java.lang.String HMAC_SHA1 = "HmacSHA1";
-    field public static final java.lang.String HMAC_SHA224 = "HmacSHA224";
-    field public static final java.lang.String HMAC_SHA256 = "HmacSHA256";
-    field public static final java.lang.String HMAC_SHA384 = "HmacSHA384";
-    field public static final java.lang.String HMAC_SHA512 = "HmacSHA512";
-    field public static final java.lang.String RSA = "RSA";
-  }
-
-  public static abstract class KeyStoreKeyProperties.AlgorithmEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.BlockMode {
-    field public static final java.lang.String CBC = "CBC";
-    field public static final java.lang.String CTR = "CTR";
-    field public static final java.lang.String ECB = "ECB";
-    field public static final java.lang.String GCM = "GCM";
-  }
-
-  public static abstract class KeyStoreKeyProperties.BlockModeEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Digest {
-    field public static final java.lang.String MD5 = "MD5";
-    field public static final java.lang.String NONE = "NONE";
-    field public static final java.lang.String SHA1 = "SHA-1";
-    field public static final java.lang.String SHA224 = "SHA-224";
-    field public static final java.lang.String SHA256 = "SHA-256";
-    field public static final java.lang.String SHA384 = "SHA-384";
-    field public static final java.lang.String SHA512 = "SHA-512";
-  }
-
-  public static abstract class KeyStoreKeyProperties.DigestEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.EncryptionPadding {
-    field public static final java.lang.String NONE = "NoPadding";
-    field public static final java.lang.String PKCS7 = "PKCS7Padding";
-    field public static final java.lang.String RSA_OAEP = "OAEPPadding";
-    field public static final java.lang.String RSA_PKCS1 = "PKCS1Padding";
-  }
-
-  public static abstract class KeyStoreKeyProperties.EncryptionPaddingEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Origin {
-    field public static final int GENERATED = 1; // 0x1
-    field public static final int IMPORTED = 2; // 0x2
-    field public static final int UNKNOWN = 4; // 0x4
-  }
-
-  public static abstract class KeyStoreKeyProperties.OriginEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.Purpose {
-    field public static final int DECRYPT = 2; // 0x2
-    field public static final int ENCRYPT = 1; // 0x1
-    field public static final int SIGN = 4; // 0x4
-    field public static final int VERIFY = 8; // 0x8
-  }
-
-  public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class KeyStoreKeyProperties.SignaturePadding {
-    field public static final java.lang.String RSA_PKCS1 = "PKCS1";
-    field public static final java.lang.String RSA_PSS = "PSS";
-  }
-
-  public static abstract class KeyStoreKeyProperties.SignaturePaddingEnum implements java.lang.annotation.Annotation {
+    field public static final java.lang.String BLOCK_MODE_CBC = "CBC";
+    field public static final java.lang.String BLOCK_MODE_CTR = "CTR";
+    field public static final java.lang.String BLOCK_MODE_ECB = "ECB";
+    field public static final java.lang.String BLOCK_MODE_GCM = "GCM";
+    field public static final java.lang.String DIGEST_MD5 = "MD5";
+    field public static final java.lang.String DIGEST_NONE = "NONE";
+    field public static final java.lang.String DIGEST_SHA1 = "SHA-1";
+    field public static final java.lang.String DIGEST_SHA224 = "SHA-224";
+    field public static final java.lang.String DIGEST_SHA256 = "SHA-256";
+    field public static final java.lang.String DIGEST_SHA384 = "SHA-384";
+    field public static final java.lang.String DIGEST_SHA512 = "SHA-512";
+    field public static final java.lang.String ENCRYPTION_PADDING_NONE = "NoPadding";
+    field public static final java.lang.String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
+    field public static final java.lang.String ENCRYPTION_PADDING_RSA_OAEP = "OAEPPadding";
+    field public static final java.lang.String ENCRYPTION_PADDING_RSA_PKCS1 = "PKCS1Padding";
+    field public static final java.lang.String KEY_ALGORITHM_AES = "AES";
+    field public static final java.lang.String KEY_ALGORITHM_EC = "EC";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA224 = "HmacSHA224";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA256 = "HmacSHA256";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA384 = "HmacSHA384";
+    field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA512 = "HmacSHA512";
+    field public static final java.lang.String KEY_ALGORITHM_RSA = "RSA";
+    field public static final int ORIGIN_GENERATED = 1; // 0x1
+    field public static final int ORIGIN_IMPORTED = 2; // 0x2
+    field public static final int ORIGIN_UNKNOWN = 4; // 0x4
+    field public static final int PURPOSE_DECRYPT = 2; // 0x2
+    field public static final int PURPOSE_ENCRYPT = 1; // 0x1
+    field public static final int PURPOSE_SIGN = 4; // 0x4
+    field public static final int PURPOSE_VERIFY = 8; // 0x8
+    field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
+    field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
 
   public class KeyStoreKeySpec implements java.security.spec.KeySpec {
@@ -32222,23 +32174,15 @@
     ctor public Call.Listener();
   }
 
-  public final class CameraCapabilities implements android.os.Parcelable {
-    ctor public CameraCapabilities(int, int);
-    method public int describeContents();
-    method public int getHeight();
-    method public int getWidth();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.telecom.CameraCapabilities> CREATOR;
-  }
-
   public abstract class Conference implements android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
     method public final void destroy();
     method public final android.telecom.AudioState getAudioState();
     method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
-    method public final long getConnectTimeMillis();
+    method public final deprecated long getConnectTimeMillis();
     method public final int getConnectionCapabilities();
+    method public final long getConnectionTime();
     method public final java.util.List<android.telecom.Connection> getConnections();
     method public final android.telecom.DisconnectCause getDisconnectCause();
     method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
@@ -32261,8 +32205,9 @@
     method public final void removeConnection(android.telecom.Connection);
     method public final void setActive();
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
-    method public void setConnectTimeMillis(long);
+    method public final deprecated void setConnectTimeMillis(long);
     method public final void setConnectionCapabilities(int);
+    method public final void setConnectionTime(long);
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setOnHold();
     method public final void setStatusHints(android.telecom.StatusHints);
@@ -32357,7 +32302,7 @@
   public static abstract class Connection.VideoProvider {
     ctor public Connection.VideoProvider();
     method public void changeCallDataUsage(long);
-    method public void changeCameraCapabilities(android.telecom.CameraCapabilities);
+    method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
     method public void changePeerDimensions(int, int);
     method public void changeVideoQuality(int);
     method public void handleCallSessionEvent(int);
@@ -32492,7 +32437,7 @@
     ctor public InCallService.VideoCall.Callback();
     method public abstract void onCallDataUsageChanged(long);
     method public abstract void onCallSessionEvent(int);
-    method public abstract void onCameraCapabilitiesChanged(android.telecom.CameraCapabilities);
+    method public abstract void onCameraCapabilitiesChanged(android.telecom.VideoProfile.CameraCapabilities);
     method public abstract void onPeerDimensionsChanged(int, int);
     method public abstract void onSessionModifyRequestReceived(android.telecom.VideoProfile);
     method public abstract void onSessionModifyResponseReceived(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
@@ -32518,7 +32463,7 @@
     method public void onCanAddCallChanged(android.telecom.Phone, boolean);
   }
 
-  public class PhoneAccount implements android.os.Parcelable {
+  public final class PhoneAccount implements android.os.Parcelable {
     method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
     method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
     method public int describeContents();
@@ -32571,7 +32516,7 @@
     method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
   }
 
-  public class PhoneAccountHandle implements android.os.Parcelable {
+  public final class PhoneAccountHandle implements android.os.Parcelable {
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String, android.os.UserHandle);
     method public int describeContents();
@@ -32748,6 +32693,15 @@
     field public static final int QUALITY_MEDIUM = 2; // 0x2
   }
 
+  public static final class VideoProfile.CameraCapabilities implements android.os.Parcelable {
+    ctor public VideoProfile.CameraCapabilities(int, int);
+    method public int describeContents();
+    method public int getHeight();
+    method public int getWidth();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile.CameraCapabilities> CREATOR;
+  }
+
   public static class VideoProfile.VideoState {
     ctor public VideoProfile.VideoState();
     method public static boolean isAudioOnly(int);
@@ -36796,6 +36750,7 @@
     method public int getFlags();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
+    method public android.view.Display.Mode getMode();
     method public java.lang.String getName();
     method public deprecated int getOrientation();
     method public deprecated int getPixelFormat();
@@ -36807,7 +36762,8 @@
     method public int getRotation();
     method public void getSize(android.graphics.Point);
     method public int getState();
-    method public float[] getSupportedRefreshRates();
+    method public android.view.Display.Mode[] getSupportedModes();
+    method public deprecated float[] getSupportedRefreshRates();
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
@@ -36822,6 +36778,16 @@
     field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
+  public static final class Display.Mode implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getModeId();
+    method public int getPhysicalHeight();
+    method public int getPhysicalWidth();
+    method public float getRefreshRate();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR;
+  }
+
   public class DragEvent implements android.os.Parcelable {
     method public int describeContents();
     method public int getAction();
@@ -39615,7 +39581,8 @@
     field public float horizontalWeight;
     field public deprecated int memoryType;
     field public java.lang.String packageName;
-    field public float preferredRefreshRate;
+    field public int preferredDisplayModeId;
+    field public deprecated float preferredRefreshRate;
     field public int rotationAnimation;
     field public float screenBrightness;
     field public int screenOrientation;
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index a3eceb5..7a894ae 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -101,8 +101,8 @@
     void getActivityEnergyInfoFromController();
     BluetoothActivityEnergyInfo reportActivityInfo();
 
-    // for dumpsys support
-    String dump();
+    // For dumpsys support
+    void dump(in ParcelFileDescriptor fd);
     void onLeServiceUp();
     void onBrEdrDown();
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6a98950..a434c7b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -134,7 +134,15 @@
      * explicitly set if desired.
      *
      * @see #getSharedPreferences
+     *
+     * @deprecated MODE_MULTI_PROCESS does not work reliably in
+     * some versions of Android, and furthermore does not provide any
+     * mechanism for reconciling concurrent modifications across
+     * processes.  Applications should not attempt to use it.  Instead,
+     * they should use an explicit cross-process data management
+     * approach such as {@link android.content.ContentProvider ContentProvider}.
      */
+    @Deprecated
     public static final int MODE_MULTI_PROCESS = 0x0004;
 
     /**
@@ -604,11 +612,7 @@
      * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()).
      * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
      * default operation, {@link #MODE_WORLD_READABLE}
-     * and {@link #MODE_WORLD_WRITEABLE} to control permissions.  The bit
-     * {@link #MODE_MULTI_PROCESS} can also be used if multiple processes
-     * are mutating the same SharedPreferences file.  {@link #MODE_MULTI_PROCESS}
-     * is always on in apps targeting Gingerbread (Android 2.3) and below, and
-     * off by default in later versions.
+     * and {@link #MODE_WORLD_WRITEABLE} to control permissions.
      *
      * @return The single {@link SharedPreferences} instance that can be used
      *         to retrieve and modify the preference values.
@@ -616,7 +620,6 @@
      * @see #MODE_PRIVATE
      * @see #MODE_WORLD_READABLE
      * @see #MODE_WORLD_WRITEABLE
-     * @see #MODE_MULTI_PROCESS
      */
     public abstract SharedPreferences getSharedPreferences(String name,
             int mode);
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index ef71c42..f70e075 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -177,13 +177,16 @@
      *                               was explicitly closed, a new session has been created
      *                               or the camera device has been closed.
      * @throws IllegalArgumentException if the request targets no Surfaces or Surfaces that are not
-     *                                  configured as outputs for this session; or a reprocess
-     *                                  capture request is submitted in a non-reprocessible capture
-     *                                  session; or the reprocess capture request was created with
-     *                                  a {@link TotalCaptureResult} from a different session; or
-     *                                  the capture targets a Surface in the middle of being
-     *                                  {@link #prepare prepared}; or the handler is null, the
-     *                                  listener is not null, and the calling thread has no looper.
+     *                                  configured as outputs for this session; or the request
+     *                                  targets a set of Surfaces that cannot be submitted
+     *                                  simultaneously in a reprocessible capture session; or a
+     *                                  reprocess capture request is submitted in a
+     *                                  non-reprocessible capture session; or the reprocess capture
+     *                                  request was created with a {@link TotalCaptureResult} from
+     *                                  a different session; or the capture targets a Surface in
+     *                                  the middle of being {@link #prepare prepared}; or the
+     *                                  handler is null, the listener is not null, and the calling
+     *                                  thread has no looper.
      *
      * @see #captureBurst
      * @see #setRepeatingRequest
@@ -233,14 +236,16 @@
      *                               was explicitly closed, a new session has been created
      *                               or the camera device has been closed.
      * @throws IllegalArgumentException If the requests target no Surfaces, or the requests target
-     *                                  Surfaces not currently configured as outputs; or a reprocess
-     *                                  capture request is submitted in a non-reprocessible capture
-     *                                  session; or one of the reprocess capture requests was
-     *                                  created with a {@link TotalCaptureResult} from a different
-     *                                  session; or one of the captures targets a Surface in the
-     *                                  middle of being {@link #prepare prepared}; or if the handler
-     *                                  is null, the listener is not null, and the calling thread
-     *                                  has no looper.
+     *                                  Surfaces not currently configured as outputs; or one of the
+     *                                  requests targets a set of Surfaces that cannot be submitted
+     *                                  simultaneously in a reprocessible capture session; or a
+     *                                  reprocess capture request is submitted in a
+     *                                  non-reprocessible capture session; or one of the reprocess
+     *                                  capture requests was created with a
+     *                                  {@link TotalCaptureResult} from a different session; or one
+     *                                  of the captures targets a Surface in the middle of being
+     *                                  {@link #prepare prepared}; or if the handler is null, the
+     *                                  listener is not null, and the calling thread has no looper.
      *
      * @see #capture
      * @see #setRepeatingRequest
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index e9564b3..4af7daf 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -416,24 +416,27 @@
      * ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING}) or OPAQUE
      * reprocessing
      * ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING}), besides
-     * the capture session created via {@link #createCaptureSession}, the application can also
-     * create a reprocessible capture session to submit reprocess capture requests in addition to
-     * regular capture requests. A reprocess capture request takes the next available buffer from
-     * the session's input Surface, and sends it through the camera device's processing pipeline
-     * again, to produce buffers for the request's target output Surfaces. No new image data is
-     * captured for a reprocess request. However the input buffer provided by
+     * the capture session created via {@link #createCaptureSession createCaptureSession}, the
+     * application can also create a reprocessible capture session to submit reprocess capture
+     * requests in addition to regular capture requests. A reprocess capture request takes the next
+     * available buffer from the session's input Surface, and sends it through the camera device's
+     * processing pipeline again, to produce buffers for the request's target output Surfaces. No
+     * new image data is captured for a reprocess request. However the input buffer provided by
      * the application must be captured previously by the same camera device in the same session
      * directly (e.g. for Zero-Shutter-Lag use case) or indirectly (e.g. combining multiple output
      * images).</p>
      *
      * <p>The active reprocessible capture session determines an input {@link Surface} and the set
      * of potential output Surfaces for the camera devices for each capture request. The application
-     * can use {@link #createCaptureRequest} to create regular capture requests to capture new
-     * images from the camera device, and use {@link #createReprocessCaptureRequest} to create
-     * reprocess capture requests to process buffers from the input {@link Surface}. A request may
-     * use all or only some of the outputs. All the output Surfaces in one capture request will come
-     * from the same source, either from a new capture by the camera device, or from the input
-     * Surface depending on if the request is a reprocess capture request.</p>
+     * can use {@link #createCaptureRequest createCaptureRequest} to create regular capture requests
+     * to capture new images from the camera device, and use {@link #createReprocessCaptureRequest
+     * createReprocessCaptureRequest} to create reprocess capture requests to process buffers from
+     * the input {@link Surface}. Some combinations of output Surfaces in a session may not be used
+     * in a request simultaneously. The guaranteed combinations of output Surfaces that can be used
+     * in a request simultaneously are listed in the tables under {@link #createCaptureSession
+     * createCaptureSession}. All the output Surfaces in one capture request will come from the
+     * same source, either from a new capture by the camera device, or from the input Surface
+     * depending on if the request is a reprocess capture request.</p>
      *
      * <p>Input formats and sizes supported by the camera device can be queried via
      * {@link StreamConfigurationMap#getInputFormats} and
@@ -451,6 +454,88 @@
      * {@link android.graphics.ImageFormat#PRIVATE} format. Otherwise, creating a reprocessible
      * capture session will fail.</p>
      *
+     * <p>The guaranteed stream configurations listed in
+     * {@link #createCaptureSession createCaptureSession} are also guaranteed to work for
+     * {@link #createReprocessibleCaptureSession createReprocessibleCaptureSession}. In addition,
+     * the configurations in the tables below are also guaranteed for creating a reprocessible
+     * capture session if the camera device supports YUV reprocessing or OPAQUE reprocessing.
+     * However, not all output targets used to create a reprocessible session may be used in a
+     * {@link CaptureRequest} simultaneously. The guaranteed output targets that can be included
+     * in a {@link CaptureRequest} simultaneously are listed in the tables under
+     * {@link #createCaptureSession createCaptureSession}. For example, with a FULL-capability
+     * ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL} {@code == }
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) device that supports OPAQUE
+     * reprocessing, an application can create a reprocessible capture session with 1 input,
+     * ({@code PRIV}, {@code MAXIMUM}), and 3 outputs, ({@code PRIV}, {@code MAXIMUM}),
+     * ({@code PRIV}, {@code PREVIEW}), and ({@code YUV}, {@code MAXIMUM}). However, it's not
+     * guaranteed that an application can submit a regular or reprocess capture with ({@code PRIV},
+     * {@code MAXIMUM}) and ({@code YUV}, {@code MAXIMUM}) outputs based on the table listed under
+     * {@link #createCaptureSession createCaptureSession}. In other words, use the tables below to
+     * determine the guaranteed stream configurations for creating a reprocessible capture session,
+     * and use the tables under {@link #createCaptureSession createCaptureSession} to determine the
+     * guaranteed output targets that can be submitted in a regular or reprocess
+     * {@link CaptureRequest} simultaneously.</p>
+     *
+     * <style scoped>
+     *  #rb { border-right-width: thick; }
+     * </style>
+     *
+     * <p>Limited-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
+     * support at least the following stream combinations for creating a reprocessible capture
+     * session in addition to those listed in {@link #createCaptureSession createCaptureSession} for
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+     *
+     * <table>
+     * <tr><th colspan="11">LIMITED-level additional guaranteed configurations for creating a reprocessible capture session<br>({@code PRIV} input is guaranteed only if OPAQUE reprocessing is supported. {@code YUV} input is guaranteed only if YUV reprocessing is supported)</th></tr>
+     * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td></td><td id="rb"></td> <td>No-viewfinder still image reprocessing.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>ZSL(Zero-Shutter-Lag) still imaging.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>ZSL still and in-app processing imaging.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>ZSL in-app processing with still capture.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>FULL-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
+     * support at least the following stream combinations for creating a reprocessible capture
+     * session in addition to those for
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+     *
+     * <table>
+     * <tr><th colspan="11">FULL-capability additional guaranteed configurations for creating a reprocessible capture session<br>({@code PRIV} input is guaranteed only if OPAQUE reprocessing is supported. {@code YUV} input is guaranteed only if YUV reprocessing is supported)</th></tr>
+     * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td></td><td id="rb"></td> <td></td><td id="rb"></td> <td>Maximum-resolution multi-frame image fusion in-app processing with regular preview.</td> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td></td><td id="rb"></td> <td></td><td id="rb"></td> <td>Maximum-resolution multi-frame image fusion two-input in-app processing.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code RECORD}</td> <td></td><td id="rb"></td> <td>High-resolution ZSL in-app video processing with regular preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Maximum-resolution ZSL in-app processing with regular preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Maximum-resolution two-input ZSL in-app processing.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code RECORD}</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD}</td> <td>High-resolution ZSL in-app video processing and video snapshot with regular preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Maximum-resolution two-input ZSL in-app processing with regular preview.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>ZSL still capture and in-app processing.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
+     * at least the following stream combinations for creating a reprocessible capture session
+     * on both {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices
+     *
+     * <table>
+     * <tr><th colspan="11">RAW-capability additional guaranteed configurations for creating a reprocessible capture session<br>({@code PRIV} input is guaranteed only if OPAQUE reprocessing is supported. {@code YUV} input is guaranteed only if YUV reprocessing is supported)</th></tr>
+     * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Mutually exclusive ZSL in-app processing and DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>Mutually exclusive ZSL in-app processing and preview with DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>Mutually exclusive ZSL two-input in-app processing and DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>Mutually exclusive ZSL still capture and preview with DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>Mutually exclusive ZSL in-app processing with still capture and DNG capture.</td> </tr>
+     * </table><br>
+     * </p>
+     *
      * @param inputConfig The configuration for the input {@link Surface}
      * @param outputs The new set of Surfaces that should be made available as
      *                targets for captured image data.
@@ -466,6 +551,7 @@
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
      *
+     * @see #createCaptureSession
      * @see CameraCaptureSession
      * @see StreamConfigurationMap#getInputFormats
      * @see StreamConfigurationMap#getInputSizes
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 02793f1..aa697ea 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -125,11 +125,13 @@
      * mirroring.
      * @param requestedRefreshRate The preferred refresh rate for the top-most visible window that
      * has a preference.
+     * @param requestedModeId The preferred mode id for the top-most visible window that has a
+     * preference.
      * @param inTraversal True if called from WindowManagerService during a window traversal
      * prior to call to performTraversalInTransactionFromWindowManager.
      */
     public abstract void setDisplayProperties(int displayId, boolean hasContent,
-            float requestedRefreshRate, boolean inTraversal);
+            float requestedRefreshRate, int requestedModeId, boolean inTraversal);
 
     /**
      * Applies an offset to the contents of a display, for example to avoid burn-in.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d8c3361..26878c0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -496,6 +496,8 @@
      * Tests if a given integer represents a valid network type.
      * @param networkType the type to be tested
      * @return a boolean.  {@code true} if the type is valid, else {@code false}
+     * @deprecated All APIs accepting a network type are deprecated. There should be no need to
+     *             validate a network type.
      */
     public static boolean isNetworkTypeValid(int networkType) {
         return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dc70d7b..d3a5561 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5517,6 +5517,12 @@
         public static final String APP_IDLE_DURATION = "app_idle_duration";
 
         /**
+         * Controls whether double tap to wake is enabled.
+         * @hide
+         */
+        public static final String DOUBLE_TAP_TO_WAKE = "double_tap_to_wake";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -5571,7 +5577,8 @@
             MOUNT_UMS_PROMPT,
             MOUNT_UMS_NOTIFY_ENABLED,
             UI_NIGHT_MODE,
-            SLEEP_TIMEOUT
+            SLEEP_TIMEOUT,
+            DOUBLE_TAP_TO_WAKE,
         };
 
         /**
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 79a8489..d2b6533 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -209,7 +209,7 @@
     private static float getRefreshRate() {
         DisplayInfo di = DisplayManagerGlobal.getInstance().getDisplayInfo(
                 Display.DEFAULT_DISPLAY);
-        return di.refreshRate;
+        return di.getMode().getRefreshRate();
     }
 
     /**
diff --git a/telecomm/java/android/telecom/CameraCapabilities.aidl b/core/java/android/view/Display.aidl
similarity index 68%
rename from telecomm/java/android/telecom/CameraCapabilities.aidl
rename to core/java/android/view/Display.aidl
index c8e0c5e..42bba44 100644
--- a/telecomm/java/android/telecom/CameraCapabilities.aidl
+++ b/core/java/android/view/Display.aidl
@@ -1,22 +1,19 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
+/**
+ * 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
+ *     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
+ * limitations under the License.
  */
 
-package android.telecom;
+package android.view;
 
-/**
- * {@hide}
- */
-parcelable CameraCapabilities;
+parcelable Display.Mode;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 71e2251..d4b971a 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,8 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
 import android.util.DisplayMetrics;
@@ -619,18 +621,44 @@
     public float getRefreshRate() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.refreshRate;
+            return mDisplayInfo.getMode().getRefreshRate();
         }
     }
 
     /**
      * Get the supported refresh rates of this display in frames per second.
+     * <p>
+     * This method only returns refresh rates for the display's default modes. For more options, use
+     * {@link #getSupportedModes()}.
+     *
+     * @deprecated use {@link #getSupportedModes()} instead
      */
+    @Deprecated
     public float[] getSupportedRefreshRates() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            final float[] refreshRates = mDisplayInfo.supportedRefreshRates;
-            return Arrays.copyOf(refreshRates, refreshRates.length);
+            return mDisplayInfo.getDefaultRefreshRates();
+        }
+    }
+
+    /**
+     * Returns the active mode of the display.
+     */
+    public Mode getMode() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.getMode();
+        }
+    }
+
+    /**
+     * Gets the supported modes of this display.
+     */
+    public Mode[] getSupportedModes() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            final Display.Mode[] modes = mDisplayInfo.supportedModes;
+            return Arrays.copyOf(modes, modes.length);
         }
     }
 
@@ -862,4 +890,152 @@
     public static boolean isSuspendedState(int state) {
         return state == STATE_OFF || state == STATE_DOZE_SUSPEND;
     }
+
+    /**
+     * A mode supported by a given display.
+     *
+     * @see Display#getSupportedModes()
+     */
+    public static final class Mode implements Parcelable {
+        /**
+         * @hide
+         */
+        public static final Mode[] EMPTY_ARRAY = new Mode[0];
+
+        private final int mModeId;
+        private final int mWidth;
+        private final int mHeight;
+        private final float mRefreshRate;
+
+        /**
+         * @hide
+         */
+        public Mode(int modeId, int width, int height, float refreshRate) {
+            mModeId = modeId;
+            mWidth = width;
+            mHeight = height;
+            mRefreshRate = refreshRate;
+        }
+
+        /**
+         * Returns this mode's id.
+         */
+        public int getModeId() {
+            return mModeId;
+        }
+
+        /**
+         * Returns the physical width of the display in pixels when configured in this mode's
+         * resolution.
+         * <p>
+         * Note that due to application UI scaling, the number of pixels made available to
+         * applications when the mode is active (as reported by {@link Display#getWidth()} may
+         * differ from the mode's actual resolution (as reported by this function).
+         * <p>
+         * For example, applications running on a 4K display may have their UI laid out and rendered
+         * in 1080p and then scaled up. Applications can take advantage of the extra resolution by
+         * rendering content through a {@link android.view.SurfaceView} using full size buffers.
+         */
+        public int getPhysicalWidth() {
+            return mWidth;
+        }
+
+        /**
+         * Returns the physical height of the display in pixels when configured in this mode's
+         * resolution.
+         * <p>
+         * Note that due to application UI scaling, the number of pixels made available to
+         * applications when the mode is active (as reported by {@link Display#getHeight()} may
+         * differ from the mode's actual resolution (as reported by this function).
+         * <p>
+         * For example, applications running on a 4K display may have their UI laid out and rendered
+         * in 1080p and then scaled up. Applications can take advantage of the extra resolution by
+         * rendering content through a {@link android.view.SurfaceView} using full size buffers.
+         */
+        public int getPhysicalHeight() {
+            return mHeight;
+        }
+
+        /**
+         * Returns the refresh rate in frames per second.
+         */
+        public float getRefreshRate() {
+            return mRefreshRate;
+        }
+
+        /**
+         * Returns {@code true} if this mode matches the given parameters.
+         *
+         * @hide
+         */
+        public boolean matches(int width, int height, float refreshRate) {
+            return mWidth == width &&
+                    mHeight == height &&
+                    Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (!(other instanceof Mode)) {
+                return false;
+            }
+            Mode that = (Mode) other;
+            return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate);
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 1;
+            hash = hash * 17 + mModeId;
+            hash = hash * 17 + mWidth;
+            hash = hash * 17 + mHeight;
+            hash = hash * 17 + Float.floatToIntBits(mRefreshRate);
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder("{")
+                    .append("id=").append(mModeId)
+                    .append(", width=").append(mWidth)
+                    .append(", height=").append(mHeight)
+                    .append(", fps=").append(mRefreshRate)
+                    .append("}")
+                    .toString();
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        private Mode(Parcel in) {
+            this(in.readInt(), in.readInt(), in.readInt(), in.readFloat());
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int parcelableFlags) {
+            out.writeInt(mModeId);
+            out.writeInt(mWidth);
+            out.writeInt(mHeight);
+            out.writeFloat(mRefreshRate);
+        }
+
+        @SuppressWarnings("hiding")
+        public static final Parcelable.Creator<Mode> CREATOR
+                = new Parcelable.Creator<Mode>() {
+            @Override
+            public Mode createFromParcel(Parcel in) {
+                return new Mode(in);
+            }
+
+            @Override
+            public Mode[] newArray(int size) {
+                return new Mode[size];
+            }
+        };
+    }
 }
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 243961c..b9fde8a 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -20,11 +20,11 @@
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 
 import java.util.Arrays;
 
-import libcore.util.EmptyArray;
 import libcore.util.Objects;
 
 /**
@@ -155,18 +155,19 @@
     public int rotation;
 
     /**
-     * The refresh rate of this display in frames per second.
-     * <p>
-     * The value of this field is indeterminate if the logical display is presented on
-     * more than one physical display.
-     * </p>
+     * The active display mode.
      */
-    public float refreshRate;
+    public int modeId;
 
     /**
-     * The supported refresh rates of this display at the current resolution in frames per second.
+     * The default display mode.
      */
-    public float[] supportedRefreshRates = EmptyArray.FLOAT;
+    public int defaultModeId;
+
+    /**
+     * The supported modes of this display.
+     */
+    public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
 
     /**
      * The logical display density which is the basis for density-independent
@@ -276,7 +277,8 @@
                 && overscanRight == other.overscanRight
                 && overscanBottom == other.overscanBottom
                 && rotation == other.rotation
-                && refreshRate == other.refreshRate
+                && modeId == other.modeId
+                && defaultModeId == other.defaultModeId
                 && logicalDensityDpi == other.logicalDensityDpi
                 && physicalXDpi == other.physicalXDpi
                 && physicalYDpi == other.physicalYDpi
@@ -312,9 +314,9 @@
         overscanRight = other.overscanRight;
         overscanBottom = other.overscanBottom;
         rotation = other.rotation;
-        refreshRate = other.refreshRate;
-        supportedRefreshRates = Arrays.copyOf(
-                other.supportedRefreshRates, other.supportedRefreshRates.length);
+        modeId = other.modeId;
+        defaultModeId = other.defaultModeId;
+        supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
         logicalDensityDpi = other.logicalDensityDpi;
         physicalXDpi = other.physicalXDpi;
         physicalYDpi = other.physicalYDpi;
@@ -344,8 +346,13 @@
         overscanRight = source.readInt();
         overscanBottom = source.readInt();
         rotation = source.readInt();
-        refreshRate = source.readFloat();
-        supportedRefreshRates = source.createFloatArray();
+        modeId = source.readInt();
+        defaultModeId = source.readInt();
+        int nModes = source.readInt();
+        supportedModes = new Display.Mode[nModes];
+        for (int i = 0; i < nModes; i++) {
+            supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
+        }
         logicalDensityDpi = source.readInt();
         physicalXDpi = source.readFloat();
         physicalYDpi = source.readFloat();
@@ -377,8 +384,12 @@
         dest.writeInt(overscanRight);
         dest.writeInt(overscanBottom);
         dest.writeInt(rotation);
-        dest.writeFloat(refreshRate);
-        dest.writeFloatArray(supportedRefreshRates);
+        dest.writeInt(modeId);
+        dest.writeInt(defaultModeId);
+        dest.writeInt(supportedModes.length);
+        for (int i = 0; i < supportedModes.length; i++) {
+            supportedModes[i].writeToParcel(dest, flags);
+        }
         dest.writeInt(logicalDensityDpi);
         dest.writeFloat(physicalXDpi);
         dest.writeFloat(physicalYDpi);
@@ -395,6 +406,61 @@
         return 0;
     }
 
+    public Display.Mode getMode() {
+        return findMode(modeId);
+    }
+
+    public Display.Mode getDefaultMode() {
+        return findMode(defaultModeId);
+    }
+
+    private Display.Mode findMode(int id) {
+        for (int i = 0; i < supportedModes.length; i++) {
+            if (supportedModes[i].getModeId() == id) {
+                return supportedModes[i];
+            }
+        }
+        throw new IllegalStateException("Unable to locate mode " + id);
+    }
+
+    /**
+     * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable
+     * mode could be found.
+     */
+    public int findDefaultModeByRefreshRate(float refreshRate) {
+        Display.Mode[] modes = supportedModes;
+        Display.Mode defaultMode = getDefaultMode();
+        for (int i = 0; i < modes.length; i++) {
+            if (modes[i].matches(
+                    defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) {
+                return modes[i].getModeId();
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Returns the list of supported refresh rates in the default mode.
+     */
+    public float[] getDefaultRefreshRates() {
+        Display.Mode[] modes = supportedModes;
+        ArraySet<Float> rates = new ArraySet<>();
+        Display.Mode defaultMode = getDefaultMode();
+        for (int i = 0; i < modes.length; i++) {
+            Display.Mode mode = modes[i];
+            if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth()
+                    && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) {
+                rates.add(mode.getRefreshRate());
+            }
+        }
+        float[] result = new float[rates.size()];
+        int i = 0;
+        for (Float rate : rates) {
+            result[i++] = rate;
+        }
+        return result;
+    }
+
     public void getAppMetrics(DisplayMetrics outMetrics) {
         getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
     }
@@ -490,10 +556,12 @@
         sb.append(smallestNominalAppWidth);
         sb.append(" x ");
         sb.append(smallestNominalAppHeight);
-        sb.append(", ");
-        sb.append(refreshRate);
-        sb.append(" fps, supportedRefreshRates ");
-        sb.append(Arrays.toString(supportedRefreshRates));
+        sb.append(", mode ");
+        sb.append(modeId);
+        sb.append(", defaultMode ");
+        sb.append(defaultModeId);
+        sb.append(", modes ");
+        sb.append(Arrays.toString(supportedModes));
         sb.append(", rotation ");
         sb.append(rotation);
         sb.append(", density ");
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2797b6e..7976ca4 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -101,7 +101,7 @@
      * the given view hierarchy's {@link View#onDetachedFromWindow()
      * View.onDetachedFromWindow()} methods before returning.  This is not
      * for normal applications; using it correctly requires great care.
-     * 
+     *
      * @param view The view to be removed.
      */
     public void removeViewImmediate(View view);
@@ -115,7 +115,7 @@
          */
         @ViewDebug.ExportedProperty
         public int x;
-        
+
         /**
          * Y position for this window.  With the default gravity it is ignored.
          * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides
@@ -228,12 +228,12 @@
             @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
         })
         public int type;
-    
+
         /**
          * Start of window types that represent normal application windows.
          */
         public static final int FIRST_APPLICATION_WINDOW = 1;
-        
+
         /**
          * Window type: an application window that serves as the "base" window
          * of the overall application; all other application windows will
@@ -241,14 +241,14 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_BASE_APPLICATION   = 1;
-        
+
         /**
          * Window type: a normal application window.  The {@link #token} must be
          * an Activity token identifying who the window belongs to.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_APPLICATION        = 2;
-    
+
         /**
          * Window type: special application window that is displayed while the
          * application is starting.  Not for use by applications themselves;
@@ -257,7 +257,7 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_APPLICATION_STARTING = 3;
-    
+
         /**
          * End of types of application windows.
          */
@@ -330,14 +330,14 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
-    
+
         /**
          * Window type: the search bar.  There can be only one search bar
          * window; it is placed at the top of the screen.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
-    
+
         /**
          * Window type: phone.  These are non-application windows providing
          * user interaction with the phone (in particular incoming calls).
@@ -346,7 +346,7 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
-    
+
         /**
          * Window type: system window, such as low power alert. These windows
          * are always on top of application windows.
@@ -366,7 +366,7 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
-        
+
         /**
          * Window type: system overlay windows, which need to be displayed
          * on top of everything else.  These windows must not take input
@@ -374,7 +374,7 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
-        
+
         /**
          * Window type: priority phone UI, which needs to be displayed even if
          * the keyguard is active.  These windows must not take input
@@ -382,26 +382,26 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
-        
+
         /**
          * Window type: panel that slides out from the status bar
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
-    
+
         /**
          * Window type: dialogs that the keyguard shows
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
-        
+
         /**
          * Window type: internal system error windows, appear on top of
          * everything they can.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
-        
+
         /**
          * Window type: internal input methods windows, which appear above
          * the normal UI.  Application windows may be resized or panned to keep
@@ -581,16 +581,16 @@
         /** @deprecated this is ignored, this value is set automatically when needed. */
         @Deprecated
         public static final int MEMORY_TYPE_PUSH_BUFFERS = 3;
-        
+
         /**
          * @deprecated this is ignored
          */
         @Deprecated
         public int memoryType;
-        
+
         /** Window flag: as long as this window is visible to the user, allow
-         *  the lock screen to activate while the screen is on. 
-         *  This can be used independently, or in combination with 
+         *  the lock screen to activate while the screen is on.
+         *  This can be used independently, or in combination with
          *  {@link #FLAG_KEEP_SCREEN_ON} and/or {@link #FLAG_SHOW_WHEN_LOCKED} */
         public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001;
 
@@ -608,26 +608,26 @@
          * instead go to whatever focusable window is behind it.  This flag
          * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that
          * is explicitly set.
-         * 
+         *
          * <p>Setting this flag also implies that the window will not need to
          * interact with
-         * a soft input method, so it will be Z-ordered and positioned 
+         * a soft input method, so it will be Z-ordered and positioned
          * independently of any active input method (typically this means it
          * gets Z-ordered on top of the input method, so it can use the full
          * screen for its content and cover the input method if needed.  You
          * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */
         public static final int FLAG_NOT_FOCUSABLE      = 0x00000008;
-        
+
         /** Window flag: this window can never receive touch events. */
         public static final int FLAG_NOT_TOUCHABLE      = 0x00000010;
-        
+
         /** Window flag: even when this window is focusable (its
          * {@link #FLAG_NOT_FOCUSABLE} is not set), allow any pointer events
          * outside of the window to be sent to the windows behind it.  Otherwise
          * it will consume all pointer events itself, regardless of whether they
          * are inside of the window. */
         public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020;
-        
+
         /** Window flag: when set, if the device is asleep when the touch
          * screen is pressed, you will receive this first touch event.  Usually
          * the first touch event is consumed by the system since the user can
@@ -637,21 +637,21 @@
          */
         @Deprecated
         public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
-        
+
         /** Window flag: as long as this window is visible to the user, keep
          *  the device's screen turned on and bright. */
         public static final int FLAG_KEEP_SCREEN_ON     = 0x00000080;
-        
+
         /** Window flag: place the window within the entire screen, ignoring
          *  decorations around the border (such as the status bar).  The
          *  window must correctly position its contents to take the screen
          *  decoration into account.  This flag is normally set for you
          *  by Window as described in {@link Window#setFlags}. */
         public static final int FLAG_LAYOUT_IN_SCREEN   = 0x00000100;
-        
+
         /** Window flag: allow window to extend outside of the screen. */
         public static final int FLAG_LAYOUT_NO_LIMITS   = 0x00000200;
-        
+
         /**
          * Window flag: hide all screen decorations (such as the status bar) while
          * this window is displayed.  This allows the window to use the entire
@@ -673,17 +673,17 @@
          * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_Fullscreen}.</p>
          */
         public static final int FLAG_FULLSCREEN      = 0x00000400;
-        
+
         /** Window flag: override {@link #FLAG_FULLSCREEN} and force the
          *  screen decorations (such as the status bar) to be shown. */
         public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
-        
+
         /** Window flag: turn on dithering when compositing this window to
          *  the screen.
          * @deprecated This flag is no longer used. */
         @Deprecated
         public static final int FLAG_DITHER             = 0x00001000;
-        
+
         /** Window flag: treat the content of the window as secure, preventing
          * it from appearing in screenshots or from being viewed on non-secure
          * displays.
@@ -692,21 +692,21 @@
          * secure surfaces and secure displays.
          */
         public static final int FLAG_SECURE             = 0x00002000;
-        
+
         /** Window flag: a special mode where the layout parameters are used
          * to perform scaling of the surface when it is composited to the
          * screen. */
         public static final int FLAG_SCALED             = 0x00004000;
-        
+
         /** Window flag: intended for windows that will often be used when the user is
          * holding the screen against their face, it will aggressively filter the event
          * stream to prevent unintended presses in this situation that may not be
-         * desired for a particular window, when such an event stream is detected, the 
+         * desired for a particular window, when such an event stream is detected, the
          * application will receive a CANCEL motion event to indicate this so applications
-         * can handle this accordingly by taking no action on the event 
+         * can handle this accordingly by taking no action on the event
          * until the finger is released. */
         public static final int FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000;
-        
+
         /** Window flag: a special option only for use in combination with
          * {@link #FLAG_LAYOUT_IN_SCREEN}.  When requesting layout in the
          * screen your window may appear on top of or behind screen decorations
@@ -715,7 +715,7 @@
          * content is not covered by screen decorations.  This flag is normally
          * set for you by Window as described in {@link Window#setFlags}.*/
         public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
-        
+
         /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with
          * respect to how this window interacts with the current method.  That
          * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the
@@ -726,7 +726,7 @@
          * to use more space and cover the input method.
          */
         public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
-        
+
         /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you
          * can set this flag to receive a single special MotionEvent with
          * the action
@@ -736,7 +736,7 @@
          * first down as an ACTION_OUTSIDE.
          */
         public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
-        
+
         /** Window flag: special flag to let windows be shown when the screen
          * is locked. This will let application windows take precedence over
          * key guard or any other lock screens. Can be used with
@@ -766,13 +766,13 @@
          * {@link android.R.style#Theme_DeviceDefault_Wallpaper_NoTitleBar}.</p>
          */
         public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
-        
+
         /** Window flag: when set as a window is being added or made
          * visible, once the window has been shown then the system will
          * poke the power manager's user activity (as if the user had woken
          * up the device) to turn the screen on. */
         public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
-        
+
         /** Window flag: when set the window will cause the keyguard to
          * be dismissed, only if it is not a secure lock keyguard.  Because such
          * a keyguard is not needed for security, it will never re-appear if
@@ -786,7 +786,7 @@
          * also been set.
          */
         public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
-        
+
         /** Window flag: when set the window will accept for touch events
          * outside of its bounds to be sent to other windows that also
          * support split touch.  When this flag is not set, the first pointer
@@ -798,7 +798,7 @@
          * to be split across multiple windows.
          */
         public static final int FLAG_SPLIT_TOUCH = 0x00800000;
-        
+
         /**
          * <p>Indicates whether this window should be hardware accelerated.
          * Requesting hardware acceleration does not guarantee it will happen.</p>
@@ -940,7 +940,7 @@
 
         /**
          * Various behavioral options/flags.  Default is none.
-         * 
+         *
          * @see #FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
          * @see #FLAG_DIM_BEHIND
          * @see #FLAG_NOT_FOCUSABLE
@@ -1041,10 +1041,10 @@
          * as if it was.
          * Like {@link #FLAG_HARDWARE_ACCELERATED} except for trusted system windows
          * that need hardware acceleration (e.g. LockScreen), where hardware acceleration
-         * is generally disabled. This flag must be specified in addition to 
+         * is generally disabled. This flag must be specified in addition to
          * {@link #FLAG_HARDWARE_ACCELERATED} to enable hardware acceleration for system
          * windows.
-         * 
+         *
          * @hide
          */
         public static final int PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED = 0x00000001;
@@ -1055,7 +1055,7 @@
          * If certain parts of the UI that really do want to use hardware
          * acceleration, this flag can be set to force it.  This is basically
          * for the lock screen.  Anyone else using it, you are probably wrong.
-         * 
+         *
          * @hide
          */
         public static final int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED = 0x00000002;
@@ -1194,63 +1194,63 @@
             }
             return false;
         }
-        
+
         /**
          * Mask for {@link #softInputMode} of the bits that determine the
          * desired visibility state of the soft input area for this window.
          */
         public static final int SOFT_INPUT_MASK_STATE = 0x0f;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: no state has been specified.
          */
         public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please don't change the state of
          * the soft input area.
          */
         public static final int SOFT_INPUT_STATE_UNCHANGED = 1;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please hide any soft input
          * area when normally appropriate (when the user is navigating
          * forward to your window).
          */
         public static final int SOFT_INPUT_STATE_HIDDEN = 2;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please always hide any
          * soft input area when this window receives focus.
          */
         public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please show the soft
          * input area when normally appropriate (when the user is navigating
          * forward to your window).
          */
         public static final int SOFT_INPUT_STATE_VISIBLE = 4;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please always make the
          * soft input area visible when this window receives input focus.
          */
         public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
-        
+
         /**
          * Mask for {@link #softInputMode} of the bits that determine the
          * way that the window should be adjusted to accommodate the soft
          * input window.
          */
         public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
-        
+
         /** Adjustment option for {@link #softInputMode}: nothing specified.
          * The system will try to pick one or
          * the other depending on the contents of the window.
          */
         public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;
-        
+
         /** Adjustment option for {@link #softInputMode}: set to allow the
          * window to be resized when an input
          * method is shown, so that its contents are not covered by the input
@@ -1263,7 +1263,7 @@
          * not resize, but will stay fullscreen.
          */
         public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
-        
+
         /** Adjustment option for {@link #softInputMode}: set to have a window
          * pan when an input method is
          * shown, so it doesn't need to deal with resizing but just panned
@@ -1273,7 +1273,7 @@
          * the other depending on the contents of the window.
          */
         public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
-        
+
         /** Adjustment option for {@link #softInputMode}: set to have a window
          * not adjust for a shown input method.  The window will not be resized,
          * and it will not be panned to make its focus visible.
@@ -1292,7 +1292,7 @@
         /**
          * Desired operating mode for any soft input area.  May be any combination
          * of:
-         * 
+         *
          * <ul>
          * <li> One of the visibility states
          * {@link #SOFT_INPUT_STATE_UNSPECIFIED}, {@link #SOFT_INPUT_STATE_UNCHANGED},
@@ -1309,7 +1309,7 @@
          * {@link android.R.attr#windowSoftInputMode} attribute.</p>
          */
         public int softInputMode;
-        
+
         /**
          * Placement of window within the screen as per {@link Gravity}.  Both
          * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int,
@@ -1326,7 +1326,7 @@
          * @see Gravity
          */
         public int gravity;
-    
+
         /**
          * The horizontal margin, as a percentage of the container's width,
          * between the container and the widget.  See
@@ -1335,7 +1335,7 @@
          * field is added with {@link #x} to supply the <var>xAdj</var> parameter.
          */
         public float horizontalMargin;
-    
+
         /**
          * The vertical margin, as a percentage of the container's height,
          * between the container and the widget.  See
@@ -1361,26 +1361,26 @@
          * @hide
          */
         public boolean hasManualSurfaceInsets;
-    
+
         /**
          * The desired bitmap format.  May be one of the constants in
          * {@link android.graphics.PixelFormat}.  Default is OPAQUE.
          */
         public int format;
-    
+
         /**
          * A style resource defining the animations to use for this window.
          * This must be a system resource; it can not be an application resource
          * because the window manager does not have access to applications.
          */
         public int windowAnimations;
-    
+
         /**
          * An alpha value to apply to this entire window.
          * An alpha of 1.0 means fully opaque and 0.0 means fully transparent
          */
         public float alpha = 1.0f;
-    
+
         /**
          * When {@link #FLAG_DIM_BEHIND} is set, this is the amount of dimming
          * to apply.  Range is from 1.0 for completely opaque to 0.0 for no
@@ -1408,7 +1408,7 @@
          * to the hightest value when this window is in front.
          */
         public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
-    
+
         /**
          * This can be used to override the user's preferred brightness of
          * the screen.  A value of less than 0, the default, means to use the
@@ -1416,7 +1416,7 @@
          * dark to full bright.
          */
         public float screenBrightness = BRIGHTNESS_OVERRIDE_NONE;
-        
+
         /**
          * This can be used to override the standard behavior of the button and
          * keyboard backlights.  A value of less than 0, the default, means to
@@ -1450,7 +1450,7 @@
          * opaque windows have the #FLAG_FULLSCREEN bit set and are not covered
          * by other windows. All other situations default to the
          * {@link #ROTATION_ANIMATION_ROTATE} behavior.
-         * 
+         *
          * @see #ROTATION_ANIMATION_ROTATE
          * @see #ROTATION_ANIMATION_CROSSFADE
          * @see #ROTATION_ANIMATION_JUMPCUT
@@ -1462,18 +1462,18 @@
          * you.
          */
         public IBinder token = null;
-    
+
         /**
          * Name of the package owning this window.
          */
         public String packageName = null;
-        
+
         /**
          * Specific orientation value for a window.
          * May be any of the same values allowed
-         * for {@link android.content.pm.ActivityInfo#screenOrientation}. 
-         * If not set, a default value of 
-         * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} 
+         * for {@link android.content.pm.ActivityInfo#screenOrientation}.
+         * If not set, a default value of
+         * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}
          * will be used.
          */
         public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -1482,13 +1482,28 @@
          * The preferred refresh rate for the window.
          *
          * This must be one of the supported refresh rates obtained for the display(s) the window
-         * is on.
+         * is on. The selected refresh rate will be applied to the display's default mode.
+         *
+         * This value is ignored if {@link #preferredDisplayModeId} is set.
          *
          * @see Display#getSupportedRefreshRates()
+         * @deprecated use {@link #preferredDisplayModeId} instead
          */
+        @Deprecated
         public float preferredRefreshRate;
 
         /**
+         * Id of the preferred display mode for the window.
+         * <p>
+         * This must be one of the supported modes obtained for the display(s) the window is on.
+         * A value of {@code 0} means no preference.
+         *
+         * @see Display#getSupportedModes()
+         * @see Display.Mode#getModeId()
+         */
+        public int preferredDisplayModeId;
+
+        /**
          * Control the visibility of the status bar.
          *
          * @see View#STATUS_BAR_VISIBLE
@@ -1505,7 +1520,7 @@
 
         /**
          * Get callbacks about the system ui visibility changing.
-         * 
+         *
          * TODO: Maybe there should be a bitfield of optional callbacks that we need.
          *
          * @hide
@@ -1571,34 +1586,34 @@
             type = TYPE_APPLICATION;
             format = PixelFormat.OPAQUE;
         }
-        
+
         public LayoutParams(int _type) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             format = PixelFormat.OPAQUE;
         }
-    
+
         public LayoutParams(int _type, int _flags) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             flags = _flags;
             format = PixelFormat.OPAQUE;
         }
-    
+
         public LayoutParams(int _type, int _flags, int _format) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             flags = _flags;
             format = _format;
         }
-        
+
         public LayoutParams(int w, int h, int _type, int _flags, int _format) {
             super(w, h);
             type = _type;
             flags = _flags;
             format = _format;
         }
-        
+
         public LayoutParams(int w, int h, int xpos, int ypos, int _type,
                 int _flags, int _format) {
             super(w, h);
@@ -1608,14 +1623,14 @@
             flags = _flags;
             format = _format;
         }
-    
+
         public final void setTitle(CharSequence title) {
             if (null == title)
                 title = "";
-    
+
             mTitle = TextUtils.stringOrSpannedString(title);
         }
-    
+
         public final CharSequence getTitle() {
             return mTitle;
         }
@@ -1660,6 +1675,7 @@
             TextUtils.writeToParcel(mTitle, out, parcelableFlags);
             out.writeInt(screenOrientation);
             out.writeFloat(preferredRefreshRate);
+            out.writeInt(preferredDisplayModeId);
             out.writeInt(systemUiVisibility);
             out.writeInt(subtreeSystemUiVisibility);
             out.writeInt(hasSystemUiListeners ? 1 : 0);
@@ -1683,8 +1699,8 @@
                 return new LayoutParams[size];
             }
         };
-    
-    
+
+
         public LayoutParams(Parcel in) {
             width = in.readInt();
             height = in.readInt();
@@ -1709,6 +1725,7 @@
             mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
             screenOrientation = in.readInt();
             preferredRefreshRate = in.readFloat();
+            preferredDisplayModeId = in.readInt();
             systemUiVisibility = in.readInt();
             subtreeSystemUiVisibility = in.readInt();
             hasSystemUiListeners = in.readInt() != 0;
@@ -1757,6 +1774,8 @@
         /** {@hide} */
         public static final int NEEDS_MENU_KEY_CHANGED = 1 << 22;
         /** {@hide} */
+        public static final int PREFERRED_DISPLAY_MODE_ID = 1 << 23;
+        /** {@hide} */
         public static final int EVERYTHING_CHANGED = 0xffffffff;
 
         // internal buffer to backup/restore parameters under compatibility mode.
@@ -1863,7 +1882,7 @@
                 rotationAnimation = o.rotationAnimation;
                 changes |= ROTATION_ANIMATION_CHANGED;
             }
-    
+
             if (screenOrientation != o.screenOrientation) {
                 screenOrientation = o.screenOrientation;
                 changes |= SCREEN_ORIENTATION_CHANGED;
@@ -1874,6 +1893,11 @@
                 changes |= PREFERRED_REFRESH_RATE_CHANGED;
             }
 
+            if (preferredDisplayModeId != o.preferredDisplayModeId) {
+                preferredDisplayModeId = o.preferredDisplayModeId;
+                changes |= PREFERRED_DISPLAY_MODE_ID;
+            }
+
             if (systemUiVisibility != o.systemUiVisibility
                     || subtreeSystemUiVisibility != o.subtreeSystemUiVisibility) {
                 systemUiVisibility = o.systemUiVisibility;
@@ -1924,7 +1948,7 @@
             Log.d("Debug", "WindowManager.LayoutParams={title=" + mTitle + "}");
             return "";
         }
-    
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder(256);
@@ -1996,6 +2020,10 @@
                 sb.append(" preferredRefreshRate=");
                 sb.append(preferredRefreshRate);
             }
+            if (preferredDisplayModeId != 0) {
+                sb.append(" preferredDisplayMode=");
+                sb.append(preferredDisplayModeId);
+            }
             if (systemUiVisibility != 0) {
                 sb.append(" sysui=0x");
                 sb.append(Integer.toHexString(systemUiVisibility));
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 040fd37..568e160 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -350,16 +350,6 @@
      */
     private CursorAnchorInfo mCursorAnchorInfo = null;
 
-    /**
-     * The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
-     */
-    private final int[] mViewTopLeft = new int[2];
-
-    /**
-     * The matrix to convert the view location into screen coordinates in {@link #updateCursor}.
-     */
-    private final Matrix mViewToScreenMatrix = new Matrix();
-
     // -----------------------------------------------------------
 
     /**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 2e36cee..c81e2f0 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4475,7 +4475,7 @@
 
     private class CorrectionHighlighter {
         private final Path mPath = new Path();
-        private final Paint mPaint = new Paint();
+        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         private int mStart, mEnd;
         private long mFadingStartTime;
         private RectF mTempRectF;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index ff587c2..f42959f 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -26,6 +26,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Insets;
+import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Typeface;
@@ -214,7 +215,7 @@
     public Switch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
-        mTextPaint = new TextPaint();
+        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
 
         final Resources res = getResources();
         mTextPaint.density = res.getDisplayMetrics().density;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 68c49cd..574f24b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -669,11 +669,11 @@
         final Resources res = getResources();
         final CompatibilityInfo compat = res.getCompatibilityInfo();
 
-        mTextPaint = new TextPaint();
+        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
         mTextPaint.density = res.getDisplayMetrics().density;
         mTextPaint.setCompatibilityScaling(compat.applicationScale);
 
-        mHighlightPaint = new Paint();
+        mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mHighlightPaint.setCompatibilityScaling(compat.applicationScale);
 
         mMovement = getDefaultMovementMethod();
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index a0d0b20..7d56e9e 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -66,7 +66,7 @@
                         COMPACT_BITMAP_SIZE, COMPACT_BITMAP_SIZE, Bitmap.Config.ARGB_8888
                 );
                 mTempCompactBitmapCanvas = new Canvas(mTempCompactBitmap);
-                mTempCompactBitmapPaint = new Paint();
+                mTempCompactBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                 mTempCompactBitmapPaint.setFilterBitmap(true);
             }
             mTempMatrix.reset();
diff --git a/core/res/res/drawable/ic_audio_alarm.xml b/core/res/res/drawable/ic_audio_alarm.xml
index fc4bf10..96206ea 100644
--- a/core/res/res/drawable/ic_audio_alarm.xml
+++ b/core/res/res/drawable/ic_audio_alarm.xml
@@ -17,8 +17,9 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportHeight="48.0"
+        android:tint="?attr/colorControlNormal">
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_audio_alarm_mute.xml b/core/res/res/drawable/ic_audio_alarm_mute.xml
index 1d24081..7f248c3 100644
--- a/core/res/res/drawable/ic_audio_alarm_mute.xml
+++ b/core/res/res/drawable/ic_audio_alarm_mute.xml
@@ -17,8 +17,9 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportHeight="48.0"
+        android:tint="?attr/colorControlNormal">
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_audio_media.xml b/core/res/res/drawable/ic_audio_media.xml
index a453b3db..4ef5340 100644
--- a/core/res/res/drawable/ic_audio_media.xml
+++ b/core/res/res/drawable/ic_audio_media.xml
@@ -17,10 +17,11 @@
     android:height="32.0dp"
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
-    android:width="32.0dp" >
+    android:width="32.0dp"
+    android:tint="?attr/colorControlNormal">
 
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M12.0,3.0l0.0,9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12.0 6.0,14.01 6.0,16.5S8.01,21.0 10.5,21.0c2.31,0.0 4.2,-1.75 4.45,-4.0L15.0,17.0L15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0z" />
 
 </vector>
diff --git a/core/res/res/drawable/ic_audio_media_mute.xml b/core/res/res/drawable/ic_audio_media_mute.xml
index 2e7f6dc..2be6dc4 100644
--- a/core/res/res/drawable/ic_audio_media_mute.xml
+++ b/core/res/res/drawable/ic_audio_media_mute.xml
@@ -17,13 +17,14 @@
     android:height="32.0dp"
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
-    android:width="32.0dp" >
+    android:width="32.0dp"
+    android:tint="?attr/colorControlNormal">
 
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C15.0,8.8 15.0,6.0 15.0,6.0z" />
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M4.8,3.9L3.5,5.1l6.9,6.9C8.0,12.1 6.0,14.0 6.0,16.5C6.0,19.0 8.0,21.0 10.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3c0.0,0.0 0.0,-0.1 0.0,-0.1l4.0,4.0l1.3,-1.3L4.8,3.9z" />
 
 </vector>
diff --git a/core/res/res/drawable/ic_audio_ring_notif.xml b/core/res/res/drawable/ic_audio_ring_notif.xml
index 60a98ab..54c4074 100644
--- a/core/res/res/drawable/ic_audio_ring_notif.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif.xml
@@ -17,9 +17,10 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
 
     <path
-        android:fillColor="#8A000000"
+        android:fillColor="@color/black"
         android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_audio_ring_notif_mute.xml b/core/res/res/drawable/ic_audio_ring_notif_mute.xml
index 17dfa7e..b591520 100644
--- a/core/res/res/drawable/ic_audio_ring_notif_mute.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif_mute.xml
@@ -17,9 +17,10 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
 
     <path
-        android:fillColor="#8A000000"
+        android:fillColor="@color/black"
         android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" />
 </vector>
diff --git a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
index 2ed33ea..b3a2859 100644
--- a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
@@ -17,9 +17,10 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
 
     <path
-        android:fillColor="#8A000000"
+        android:fillColor="@color/black"
         android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_audio_vol.xml b/core/res/res/drawable/ic_audio_vol.xml
index a55be93..fc216e5 100644
--- a/core/res/res/drawable/ic_audio_vol.xml
+++ b/core/res/res/drawable/ic_audio_vol.xml
@@ -17,8 +17,9 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportHeight="48.0"
+        android:tint="?attr/colorControlNormal">
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,8.0L14.0,18.0L6.0,18.0zm27.0,6.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,16.11c2.96,-1.48 5.0,-4.53 5.0,-8.06zM28.0,6.46l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41s-4.22,11.69 -10.0,13.41l0.0,4.13c8.01,-1.82 14.0,-8.97 14.0,-17.54S36.01,8.28 28.0,6.46z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_audio_vol_mute.xml b/core/res/res/drawable/ic_audio_vol_mute.xml
index ab50a7d..7cf604c 100644
--- a/core/res/res/drawable/ic_audio_vol_mute.xml
+++ b/core/res/res/drawable/ic_audio_vol_mute.xml
@@ -17,8 +17,9 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportHeight="48.0"
+        android:tint="?attr/colorControlNormal">
     <path
-        android:fillColor="?android:attr/colorControlNormal"
+        android:fillColor="@color/black"
         android:pathData="M33.0,24.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,4.42l4.91,4.91c0.06,-0.42 0.09,-0.85 0.09,-1.28zm5.0,0.0c0.0,1.88 -0.41,3.65 -1.08,5.28l3.03,3.03C41.25,29.82 42.0,27.0 42.0,24.0c0.0,-8.56 -5.99,-15.72 -14.0,-17.54l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41zM8.55,6.0L6.0,8.55 15.45,18.0L6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,26.55l8.51,8.51c-1.34,1.03 -2.85,1.86 -4.51,2.36l0.0,4.13c2.75,-0.63 5.26,-1.89 7.37,-3.62L39.45,42.0 42.0,39.45l-18.0,-18.0L8.55,6.0zM24.0,8.0l-4.18,4.18L24.0,16.36L24.0,8.0z"/>
 </vector>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 59c6e4f..38bbe66 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1070,29 +1070,29 @@
              is launched that task will or will not start depending on whether the package of this
              activity has been whitelisted.
              <p>Tasks rooted at this activity can only exit lockTask mode using stopLockTask(). -->
-        <enum name="lockTaskModeDefault" value="0"/>
+        <enum name="normal" value="0"/>
         <!-- Tasks will not launch into lockTask mode and cannot be placed there using
              {@link android.app.Activity#startLockTask} or be pinned from the Overview screen.
              If the system is already in lockTask mode when a new task rooted at this activity is
              launched that task will not be started.
              <p>Note: This mode is only available to system and privileged applications.
-             Non-privileged apps with this value will be treated as lockTaskModeDefault.
+             Non-privileged apps with this value will be treated as normal.
              -->
-        <enum name="lockTaskModeNever" value="1"/>
+        <enum name="never" value="1"/>
         <!-- Tasks rooted at this activity will always launch into lockTask mode. If the system is
              already in lockTask mode when this task is launched then the new task will be launched
              on top of the current task. Tasks launched in this mode are capable of exiting
              lockTask mode using finish(), whereas tasks entering lockTask mode using
              startLockTask() must use stopLockTask() to exit.
              <p>Note: This mode is only available to system and privileged applications.
-             Non-privileged apps with this value will be treated as lockTaskModeDefault.
+             Non-privileged apps with this value will be treated as normal.
              -->
-        <enum name="lockTaskModeAlways" value="2"/>
+        <enum name="always" value="2"/>
         <!-- If the DevicePolicyManager (DPM) authorizes this package ({@link
              android.app.admin.DevicePolicyManager#setLockTaskPackages}) then this mode is
-             identical to lockTaskModeAlways. If the DPM does not authorize this package then this
-             mode is identical to lockTaskModeDefault. -->
-        <enum name="lockTaskModeIfWhitelisted" value="3"/>
+             identical to always. If the DPM does not authorize this package then this
+             mode is identical to normal. -->
+        <enum name="if_whitelisted" value="3"/>
     </attr>
     <!-- When set installer will extract native libraries. If set to false
          libraries in the apk must be stored and page-aligned.  -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7270b2c..690fd28 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2141,4 +2141,7 @@
 
     <!-- This config is ued to determine whether animations are allowed in low power mode. -->
     <bool name="config_allowAnimationsInLowPowerMode">false</bool>
+
+    <!-- Whether device supports double tap to wake -->
+    <bool name="config_supportDoubleTapWake">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e54a0b2..8f949e1 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2261,4 +2261,5 @@
   <java-symbol type="layout" name="chooser_row" />
   <java-symbol type="color" name="chooser_service_row_background_color" />
   <java-symbol type="id" name="target_badge" />
+  <java-symbol type="bool" name="config_supportDoubleTapWake" />
 </resources>
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 2e7ce56..eef8cda 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -185,50 +185,101 @@
 <p>You can check and update the installed version of these tools in the
   <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</p>
 
-<p class="note">
-  <strong>Note:</strong> Use of Support Library RenderScript APIs is not currently supported with
-  Android Studio or Gradle-based builds.
-</p>
 
-<p>To use the Support Library RenderScript APIs in Eclipse:</p>
+<p>To use the Support Library RenderScript APIs:</p>
 
 <ol>
   <li>Make sure you have the required Android SDK version and Build Tools version installed.</li>
-  <li>Open the {@code project.properties} file in the root folder of your application project.</li>
-  <li>Add the following lines to the file:
+  <li> Update the settings for the Android build process to include the RenderScript settings:
+
+    <p><strong>For Android Studio or Gradle-based builds</strong></p>
+    <ul>
+      <li>Open the {@code build.gradle} file in the app folder of your application module. </li>
+      <li>Add the following RenderScript settings to the file:
+
+<pre>
+android {
+    compileSdkVersion 19
+    buildToolsVersion "19.0.3"
+
+    defaultConfig {
+        minSdkVersion 8
+        targetSdkVersion 16
+<strong>
+        renderscriptTargetApi 18
+        renderscriptSupportModeEnabled true
+</strong>
+    }
+}
+</pre>
+
+
+    <p>The settings listed above control specific behavior in the Android build process:</p>
+
+    <ul>
+      <li>{@code renderscriptTargetApi} - Specifies the bytecode version to be generated. We
+      recommend you set this value to the highest available API level and set
+      {@code renderscriptSupportModeEnabled}
+      to {@code true}. Valid values for this setting are any integer value
+      from 11 to the most recently released API level. If your minimum SDK version specified in your
+      application manifest is set to a different value, that value is ignored and the target value
+      in the build file is used to set the minimum SDK version.</li>
+      <li>{@code renderscriptSupportModeEnabled} - Specifies that the generated bytecode should fall
+      back to a compatible version if the device it is running on does not support the target
+      version.
+      </li>
+      <li>{@code buildToolsVersion} - The version of the Android SDK build tools to use. This value
+      should be set to {@code 18.1.0} or higher. If this option is not specified, the highest
+      installed build tools version is used. You should always set this value to ensure the
+      consistency of builds across development machines with different configurations.</li>
+    </ul>
+
+    </li>
+
+    <p><strong>For Eclipse</strong></p>
+    <ul>
+      <li>Open the {@code project.properties} file in the root folder of your application project.</li>
+      <li>Add the following lines to the file:
+
 <pre>
 renderscript.target=18
 renderscript.support.mode=true
 sdk.buildtools=18.1.0
 </pre>
-  </li>
+
+      <p>The settings listed above control specific behavior in the Android build process:</p>
+
+      <ul>
+        <li>{@code renderscript.target} - Specifies the bytecode version to be generated. We
+        recommend you set this value to the highest available API level and set
+        {@code renderscript.support.mode} to {@code true}. Valid values for this setting are any
+        integer value from 11 to the most recently released API level. If your minimum SDK version
+        specified in your application manifest is set to a higher value, this value is ignored and
+        the target value is set to the minimum SDK version.</li>
+        <li>{@code renderscript.support.mode} - Specifies that the generated bytecode should fall
+        back to a compatible version if the device it is running on does not support the target version.
+        </li>
+        <li>{@code sdk.buildtools} - The version of the Android SDK build tools to use. This value
+        should be set to {@code 18.1.0} or higher. If this option is not specified, the highest
+        installed build tools version is used. You should always set this value to ensure the
+        consistency of builds across development machines with different configurations.</li>
+      </ul>
+     </li>
+
+    </ul>
+
+  </ul>
+
   <li>In your application classes that use RenderScript, add an import for the Support Library
     classes:
+
 <pre>
 import android.support.v8.renderscript.*;
 </pre>
+
   </li>
-</ol>
 
-<p>The {@code project.properties} settings listed above control specific behavior in the Android
-  build process:</p>
-
-<ul>
-  <li>{@code renderscript.target} - Specifies the bytecode version to be generated. We
-    recommend you set this value the highest available API level and set {@code
-    renderscript.support.mode} to {@code true}. Valid values for this setting are any integer value
-    from 11 to the most recently released API level. If your minimum SDK version specified in your
-    application manifest is set to a higher value, this value is ignored and the target value is set
-    to the minimum SDK version.</li>
-  <li>{@code renderscript.support.mode} - Specifies that the generated bytecode should fall
-    back to a compatible version if the device it is running on does not support the target version.
-    </li>
-  <li>{@code sdk.buildtools} - The version of the Android SDK build tools to use. This value
-    should be set to {@code 18.1.0} or higher. If this option is not specified, the highest
-    installed build tools version is used. You should always set this value to ensure the
-    consistency of builds across development machines with different configurations.</li>
-</ul>
-
+ </0l>
 
 <h2 id="using-rs-from-java">Using RenderScript from Java Code</h2>
 
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index ee1ed72..573baad 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -373,9 +373,8 @@
   developer guide.</p>
 
 <p class="note">
-  <strong>Note:</strong> Use of RenderScript with the support library is supported with the Android
-  Eclipse plugin and Ant build tools. It is <em>not currently</em> supported with Android Studio or
-  Gradle-based builds.
+  <strong>Note:</strong> Use of RenderScript with the support library is supported with Android
+  Studio and Gradle-based builds, as well as the Eclipse plugin and Ant build tools.
 </p>
 
 
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 5ccb165..871715e 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -87,8 +87,8 @@
 public class AnimationDrawable extends DrawableContainer implements Runnable, Animatable {
     private AnimationState mAnimationState;
 
-    /** The current frame, may be -1 when not animating. */
-    private int mCurFrame = -1;
+    /** The current frame, ranging from 0 to {@link #mAnimationState#getChildCount() - 1} */
+    private int mCurFrame = 0;
 
     /** Whether the drawable has an animation callback posted. */
     private boolean mRunning;
@@ -120,7 +120,7 @@
         final boolean changed = super.setVisible(visible, restart);
         if (visible) {
             if (restart || changed) {
-                boolean startFromZero = restart || mCurFrame < 0 ||
+                boolean startFromZero = restart || !mRunning ||
                         mCurFrame >= mAnimationState.getChildCount();
                 setFrame(startFromZero ? 0 : mCurFrame, true, mAnimating);
             }
@@ -194,7 +194,7 @@
 
     @Override
     public void unscheduleSelf(Runnable what) {
-        mCurFrame = -1;
+        mCurFrame = 0;
         mRunning = false;
         super.unscheduleSelf(what);
     }
@@ -245,7 +245,7 @@
      */
     public void addFrame(@NonNull Drawable frame, int duration) {
         mAnimationState.addFrame(frame, duration);
-        if (mCurFrame < 0) {
+        if (!mRunning) {
             setFrame(0, true, false);
         }
     }
@@ -272,7 +272,6 @@
         selectDrawable(frame);
         if (unschedule || animate) {
             unscheduleSelf(this);
-            mRunning = false;
         }
         if (animate) {
             // Unscheduling may have clobbered these values; restore them
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index dc9aa67..4c2817c 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -133,7 +133,7 @@
 
     private GradientState mGradientState;
 
-    private final Paint mFillPaint = new Paint();
+    private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private Rect mPadding;
     private Paint mStrokePaint;   // optional, set by the caller
     private ColorFilter mColorFilter;   // optional, set by the caller
@@ -323,7 +323,7 @@
 
     private void setStrokeInternal(int width, int color, float dashWidth, float dashGap) {
         if (mStrokePaint == null)  {
-            mStrokePaint = new Paint();
+            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             mStrokePaint.setStyle(Paint.Style.STROKE);
         }
         mStrokePaint.setStrokeWidth(width);
@@ -1802,7 +1802,7 @@
         mPadding = state.mPadding;
 
         if (state.mStrokeWidth >= 0) {
-            mStrokePaint = new Paint();
+            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             mStrokePaint.setStyle(Paint.Style.STROKE);
             mStrokePaint.setStrokeWidth(state.mStrokeWidth);
 
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index caa0787..334b3bd 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -501,7 +501,7 @@
             if (mShapeState.mPaint != null) {
                 mShapeState.mPaint = new Paint(mShapeState.mPaint);
             } else {
-                mShapeState.mPaint = new Paint();
+                mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             }
             if (mShapeState.mPadding != null) {
                 mShapeState.mPadding = new Rect(mShapeState.mPadding);
@@ -555,7 +555,7 @@
                 mAlpha = orig.mAlpha;
                 mShaderFactory = orig.mShaderFactory;
             } else {
-                mPaint = new Paint();
+                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             }
         }
 
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java
index 3f29c6a..ea90ca3 100644
--- a/keystore/java/android/security/AndroidKeyPairGenerator.java
+++ b/keystore/java/android/security/AndroidKeyPairGenerator.java
@@ -54,13 +54,13 @@
 
     public static class RSA extends AndroidKeyPairGenerator {
         public RSA() {
-            super(KeyStoreKeyProperties.Algorithm.RSA);
+            super(KeyStoreKeyProperties.KEY_ALGORITHM_RSA);
         }
     }
 
     public static class EC extends AndroidKeyPairGenerator {
         public EC() {
-            super(KeyStoreKeyProperties.Algorithm.EC);
+            super(KeyStoreKeyProperties.KEY_ALGORITHM_EC);
         }
     }
 
@@ -83,15 +83,15 @@
     private android.security.KeyStore mKeyStore;
 
     private KeyPairGeneratorSpec mSpec;
-    private @KeyStoreKeyProperties.AlgorithmEnum String mKeyAlgorithm;
+    private @KeyStoreKeyProperties.KeyAlgorithmEnum String mKeyAlgorithm;
     private int mKeyType;
     private int mKeySize;
 
-    protected AndroidKeyPairGenerator(@KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
+    protected AndroidKeyPairGenerator(@KeyStoreKeyProperties.KeyAlgorithmEnum String algorithm) {
         mAlgorithm = algorithm;
     }
 
-    public @KeyStoreKeyProperties.AlgorithmEnum String getAlgorithm() {
+    @KeyStoreKeyProperties.KeyAlgorithmEnum String getAlgorithm() {
         return mAlgorithm;
     }
 
@@ -197,7 +197,8 @@
         return certGen.generate(privateKey);
     }
 
-    private @KeyStoreKeyProperties.AlgorithmEnum String getKeyAlgorithm(KeyPairGeneratorSpec spec) {
+    private @KeyStoreKeyProperties.KeyAlgorithmEnum String getKeyAlgorithm(
+            KeyPairGeneratorSpec spec) {
         String result = spec.getKeyType();
         if (result != null) {
             return result;
@@ -249,10 +250,10 @@
     }
 
     private static String getDefaultSignatureAlgorithmForKeyAlgorithm(
-            @KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
-        if (KeyStoreKeyProperties.Algorithm.RSA.equalsIgnoreCase(algorithm)) {
+            @KeyStoreKeyProperties.KeyAlgorithmEnum String algorithm) {
+        if (KeyStoreKeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) {
             return "sha256WithRSA";
-        } else if (KeyStoreKeyProperties.Algorithm.EC.equalsIgnoreCase(algorithm)) {
+        } else if (KeyStoreKeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) {
             return "sha256WithECDSA";
         } else {
             throw new IllegalArgumentException("Unsupported key type " + algorithm);
@@ -288,7 +289,7 @@
         }
 
         KeyPairGeneratorSpec spec = (KeyPairGeneratorSpec) params;
-        @KeyStoreKeyProperties.AlgorithmEnum String keyAlgorithm = getKeyAlgorithm(spec);
+        @KeyStoreKeyProperties.KeyAlgorithmEnum String keyAlgorithm = getKeyAlgorithm(spec);
         int keyType = KeyStore.getKeyTypeForAlgorithm(keyAlgorithm);
         if (keyType == -1) {
             throw new InvalidAlgorithmParameterException(
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index 69d80e6..7ac236a 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -129,10 +129,10 @@
                 keymasterDigest = keymasterDigests.get(0);
             }
 
-            @KeyStoreKeyProperties.AlgorithmEnum String keyAlgorithmString;
+            @KeyStoreKeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
             try {
                 keyAlgorithmString =
-                        KeyStoreKeyProperties.Algorithm.fromKeymasterSecretKeyAlgorithm(
+                        KeyStoreKeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
                                 keymasterAlgorithm, keymasterDigest);
             } catch (IllegalArgumentException e) {
                 throw (UnrecoverableKeyException)
@@ -453,10 +453,10 @@
         int keymasterAlgorithm;
         int keymasterDigest;
         try {
-            keymasterAlgorithm = KeyStoreKeyProperties.Algorithm.toKeymasterSecretKeyAlgorithm(
+            keymasterAlgorithm = KeyStoreKeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(
                     keyAlgorithmString);
             keymasterDigest =
-                    KeyStoreKeyProperties.Algorithm.toKeymasterDigest(keyAlgorithmString);
+                    KeyStoreKeyProperties.KeyAlgorithm.toKeymasterDigest(keyAlgorithmString);
         } catch (IllegalArgumentException e) {
             throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString);
         }
@@ -497,7 +497,7 @@
         @KeyStoreKeyProperties.PurposeEnum int purposes = params.getPurposes();
         int[] keymasterBlockModes =
                 KeyStoreKeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
-        if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
+        if (((purposes & KeyStoreKeyProperties.PURPOSE_ENCRYPT) != 0)
                 && (params.isRandomizedEncryptionRequired())) {
             for (int keymasterBlockMode : keymasterBlockModes) {
                 if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatible(keymasterBlockMode)) {
@@ -536,7 +536,7 @@
         // TODO: Remove this once keymaster does not require us to specify the size of imported key.
         args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keyMaterial.length * 8);
 
-        if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
+        if (((purposes & KeyStoreKeyProperties.PURPOSE_ENCRYPT) != 0)
                 && (!params.isRandomizedEncryptionRequired())) {
             // Permit caller-provided IV when encrypting with this key
             args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
diff --git a/keystore/java/android/security/EcIesParameterSpec.java b/keystore/java/android/security/EcIesParameterSpec.java
index af93519..1cd8784 100644
--- a/keystore/java/android/security/EcIesParameterSpec.java
+++ b/keystore/java/android/security/EcIesParameterSpec.java
@@ -51,49 +51,44 @@
  */
 public class EcIesParameterSpec implements AlgorithmParameterSpec {
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-        PointFormat.UNSPECIFIED,
-        PointFormat.UNCOMPRESSED,
-        PointFormat.COMPRESSED,
+        POINT_FORMAT_UNSPECIFIED,
+        POINT_FORMAT_UNCOMPRESSED,
+        POINT_FORMAT_COMPRESSED,
         })
     public @interface PointFormatEnum {}
 
+    /** Unspecified EC point format. */
+    public static final int POINT_FORMAT_UNSPECIFIED = -1;
+
     /**
-     * Wire format of the EC point.
+     * Uncompressed EC point format: both coordinates are stored separately.
+     *
+     * <p>The wire format is byte {@code 0x04} followed by binary representation of the {@code x}
+     * coordinate followed by binary representation of the {@code y} coordinate. See
+     * {@code ISO 18033-2} section {@code 5.4.3}.
      */
-    public static abstract class PointFormat {
+    public static final int POINT_FORMAT_UNCOMPRESSED = 0;
 
-        private PointFormat() {}
-
-        /** Unspecified point format. */
-        public static final int UNSPECIFIED = -1;
-
-        /**
-         * Uncompressed point format: both coordinates are stored separately.
-         *
-         * <p>The wire format is byte {@code 0x04} followed by binary representation of the
-         * {@code x} coordinate followed by binary representation of the {@code y} coordinate. See
-         * {@code ISO 18033-2} section {@code 5.4.3}.
-         */
-        public static final int UNCOMPRESSED = 0;
-
-        /**
-         * Compressed point format: only one coordinate is stored.
-         *
-         * <p>The wire format is byte {@code 0x02} or {@code 0x03} (depending on the value of the
-         * stored coordinate) followed by the binary representation of the {@code x} coordinate.
-         * See {@code ISO 18033-2} section {@code 5.4.3}.
-         */
-        public static final int COMPRESSED = 1;
-    }
+    /**
+     * Compressed EC point format: only one coordinate is stored.
+     *
+     * <p>The wire format is byte {@code 0x02} or {@code 0x03} (depending on the value of the stored
+     * coordinate) followed by the binary representation of the {@code x} coordinate. See
+     * {@code ISO 18033-2} section {@code 5.4.3}.
+     */
+    public static final int POINT_FORMAT_COMPRESSED = 1;
 
     /**
      * Default parameter spec: compressed point format, {@code HKDFwithSHA256}, DEM uses 128-bit AES
      * GCM.
      */
     public static final EcIesParameterSpec DEFAULT = new EcIesParameterSpec(
-            PointFormat.COMPRESSED,
+            POINT_FORMAT_COMPRESSED,
             "HKDFwithSHA256",
             "AES/GCM/NoPadding",
             128,
@@ -123,7 +118,7 @@
     }
 
     /**
-     * Returns KEM EC point wire format or {@link PointFormat#UNSPECIFIED} if not specified.
+     * Returns KEM EC point wire format or {@link #POINT_FORMAT_UNSPECIFIED} if not specified.
      */
     public @PointFormatEnum int getKemPointFormat() {
         return mKemPointFormat;
@@ -184,7 +179,7 @@
      * Builder of {@link EcIesParameterSpec}.
      */
     public static class Builder {
-        private @PointFormatEnum int mKemPointFormat = PointFormat.UNSPECIFIED;
+        private @PointFormatEnum int mKemPointFormat = POINT_FORMAT_UNSPECIFIED;
         private String mKemKdfAlgorithm;
         private String mDemCipherTransformation;
         private int mDemCipherKeySize = 128;
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index d3dbebf..3853eca 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -266,7 +266,7 @@
      */
     public static void choosePrivateKeyAlias(@NonNull Activity activity,
             @NonNull KeyChainAliasCallback response,
-            @KeyStoreKeyProperties.AlgorithmEnum String[] keyTypes, Principal[] issuers,
+            @KeyStoreKeyProperties.KeyAlgorithmEnum String[] keyTypes, Principal[] issuers,
             @Nullable String host, int port, @Nullable String alias) {
         choosePrivateKeyAlias(activity, response, keyTypes, issuers, host, port, null, alias);
     }
@@ -312,7 +312,7 @@
      */
     public static void choosePrivateKeyAlias(@NonNull Activity activity,
             @NonNull KeyChainAliasCallback response,
-            @KeyStoreKeyProperties.AlgorithmEnum String[] keyTypes, Principal[] issuers,
+            @KeyStoreKeyProperties.KeyAlgorithmEnum String[] keyTypes, Principal[] issuers,
             @Nullable String host, int port, @Nullable String url, @Nullable String alias) {
         /*
          * TODO currently keyTypes, issuers are unused. They are meant
@@ -439,10 +439,10 @@
      * "RSA").
      */
     public static boolean isKeyAlgorithmSupported(
-            @NonNull @KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
+            @NonNull @KeyStoreKeyProperties.KeyAlgorithmEnum String algorithm) {
         final String algUpper = algorithm.toUpperCase(Locale.US);
-        return KeyStoreKeyProperties.Algorithm.EC.equals(algUpper)
-                || KeyStoreKeyProperties.Algorithm.RSA.equals(algUpper);
+        return KeyStoreKeyProperties.KEY_ALGORITHM_EC.equals(algUpper)
+                || KeyStoreKeyProperties.KEY_ALGORITHM_RSA.equals(algUpper);
     }
 
     /**
@@ -453,7 +453,7 @@
      * that makes it non-exportable.
      */
     public static boolean isBoundKeyAlgorithm(
-            @NonNull @KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
+            @NonNull @KeyStoreKeyProperties.KeyAlgorithmEnum String algorithm) {
         if (!isKeyAlgorithmSupported(algorithm)) {
             return false;
         }
diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java
index 404f939..e63566b 100644
--- a/keystore/java/android/security/KeyGeneratorSpec.java
+++ b/keystore/java/android/security/KeyGeneratorSpec.java
@@ -56,13 +56,13 @@
  * been authenticated within the last five minutes.
  * <pre> {@code
  * KeyGenerator keyGenerator = KeyGenerator.getInstance(
- *         KeyStoreKeyProperties.Algorithm.HMAC_SHA256,
+ *         KeyStoreKeyProperties.KEY_ALGORITHM_HMAC_SHA256,
  *         "AndroidKeyStore");
  * keyGenerator.initialize(
  *         new KeyGeneratorSpec.Builder(context)
  *                 .setAlias("key1")
- *                 .setPurposes(KeyStoreKeyProperties.Purpose.SIGN
- *                         | KeyStoreKeyProperties.Purpose.VERIFY)
+ *                 .setPurposes(KeyStoreKeyProperties.PURPOSE_SIGN
+ *                         | KeyStoreKeyProperties.PURPOSE_VERIFY)
  *                 // Only permit this key to be used if the user authenticated
  *                 // within the last five minutes.
  *                 .setUserAuthenticationRequired(true)
@@ -192,14 +192,21 @@
     }
 
     /**
-     * Gets the set of purposes for which the key can be used.
+     * Gets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+     * Attempts to use the key for any other purpose will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
      */
     public @KeyStoreKeyProperties.PurposeEnum int getPurposes() {
         return mPurposes;
     }
 
     /**
-     * Gets the set of padding schemes with which the key can be used when encrypting/decrypting.
+     * Gets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code NoPadding}) with
+     * which the key can be used when encrypting/decrypting. Attempts to use the key with any
+     * other padding scheme will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
@@ -207,7 +214,11 @@
     }
 
     /**
-     * Gets the set of block modes with which the key can be used.
+     * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+     * when encrypting/decrypting. Attempts to use the key with any other block modes will be
+     * rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
@@ -386,9 +397,12 @@
         }
 
         /**
-         * Sets the set of purposes for which the key can be used.
+         * Sets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+         * Attempts to use the key for any other purpose will be rejected.
          *
          * <p>This must be specified for all keys. There is no default.
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
          */
         @NonNull
         public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) {
@@ -397,11 +411,13 @@
         }
 
         /**
-         * Sets the set of padding schemes with which the key can be used when
-         * encrypting/decrypting. Attempts to use the key with any other padding scheme will be
-         * rejected.
+         * Sets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code NoPadding}) with
+         * which the key can be used when encrypting/decrypting. Attempts to use the key with any
+         * other padding scheme will be rejected.
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
          */
         @NonNull
         public Builder setEncryptionPaddings(
@@ -411,10 +427,13 @@
         }
 
         /**
-         * Sets the set of block modes with which the key can be used when encrypting/decrypting.
-         * Attempts to use the key with any other block modes will be rejected.
+         * Sets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be
+         * used when encrypting/decrypting. Attempts to use the key with any other block modes will
+         * be rejected.
          *
          * <p>This must be specified for encryption/decryption keys.
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
          */
         @NonNull
         public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index 2086ccb..b07c052 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -69,16 +69,16 @@
  * digest and only if the user has been authenticated within the last five minutes.
  * <pre> {@code
  * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
- *         KeyStoreKeyProperties.Algorithm.EC,
+ *         KeyStoreKeyProperties.KEY_ALGORITHM_EC,
  *         "AndroidKeyStore");
  * keyPairGenerator.initialize(
  *         new KeyGeneratorSpec.Builder(context)
  *                 .setAlias("key2")
- *                 .setPurposes(KeyStoreKeyProperties.Purpose.SIGN
- *                         | KeyStoreKeyProperties.Purpose.VERIFY)
- *                 .setDigests(KeyStoreKeyProperties.Digest.SHA256
- *                         | KeyStoreKeyProperties.Digest.SHA384
- *                         | KeyStoreKeyProperties.Digest.SHA512)
+ *                 .setPurposes(KeyStoreKeyProperties.PURPOSE_SIGN
+ *                         | KeyStoreKeyProperties.PURPOSE_VERIFY)
+ *                 .setDigests(KeyStoreKeyProperties.DIGEST_SHA256
+ *                         | KeyStoreKeyProperties.DIGEST_SHA384
+ *                         | KeyStoreKeyProperties.DIGEST_SHA512)
  *                 // Only permit this key to be used if the user authenticated
  *                 // within the last five minutes.
  *                 .setUserAuthenticationRequired(true)
@@ -287,10 +287,11 @@
     }
 
     /**
-     * Returns the key type (e.g., "EC", "RSA") specified by this parameter.
+     * Returns the type of key pair (e.g., {@code EC}, {@code RSA}) to be generated. See
+     * {@link KeyStoreKeyProperties}.{@code KEY_ALGORITHM} constants.
      */
     @Nullable
-    public @KeyStoreKeyProperties.AlgorithmEnum String getKeyType() {
+    public @KeyStoreKeyProperties.KeyAlgorithmEnum String getKeyType() {
         return mKeyType;
     }
 
@@ -395,14 +396,20 @@
     }
 
     /**
-     * Gets the set of purposes for which the key can be used.
+     * Gets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+     * Attempts to use the key for any other purpose will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
      */
     public @KeyStoreKeyProperties.PurposeEnum int getPurposes() {
         return mPurposes;
     }
 
     /**
-     * Gets the set of digest algorithms with which the key can be used.
+     * Gets the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384} with which the key
+     * can be used.
+     *
+     * @see KeyStoreKeyProperties.Digest
      */
     @NonNull
     public @KeyStoreKeyProperties.DigestEnum String[] getDigests() {
@@ -410,7 +417,11 @@
     }
 
     /**
-     * Gets the set of padding schemes with which the key can be used when encrypting/decrypting.
+     * Gets the set of padding schemes (e.g., {@code OEAPPadding}, {@code PKCS1Padding},
+     * {@code NoPadding}) with which the key can be used when encrypting/decrypting. Attempts to use
+     * the key with any other padding scheme will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
@@ -418,7 +429,11 @@
     }
 
     /**
-     * Gets the set of padding schemes with which the key can be used when signing/verifying.
+     * Gets the set of padding schemes (e.g., {@code PSS}, {@code PKCS#1}) with which the key
+     * can be used when signing/verifying. Attempts to use the key with any other padding scheme
+     * will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code SIGNATURE_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
@@ -426,7 +441,11 @@
     }
 
     /**
-     * Gets the set of block modes with which the key can be used.
+     * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+     * when encrypting/decrypting. Attempts to use the key with any other block modes will be
+     * rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
@@ -566,10 +585,12 @@
         }
 
         /**
-         * Sets the key type (e.g., EC, RSA) of the keypair to be created.
+         * Sets the type of key pair (e.g., {@code EC}, {@code RSA}) of the key pair to be
+         * generated. See {@link KeyStoreKeyProperties}.{@code KEY_ALGORITHM} constants.
+         *
          */
         @NonNull
-        public Builder setKeyType(@NonNull @KeyStoreKeyProperties.AlgorithmEnum String keyType)
+        public Builder setKeyType(@NonNull @KeyStoreKeyProperties.KeyAlgorithmEnum String keyType)
                 throws NoSuchAlgorithmException {
             if (keyType == null) {
                 throw new NullPointerException("keyType == null");
@@ -699,7 +720,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          *
          * @see #setKeyValidityEnd(Date)
          */
@@ -714,7 +735,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          *
          * @see #setKeyValidityStart(Date)
          * @see #setKeyValidityForConsumptionEnd(Date)
@@ -732,7 +753,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          *
          * @see #setKeyValidityForConsumptionEnd(Date)
          */
@@ -748,7 +769,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          *
          * @see #setKeyValidityForOriginationEnd(Date)
          */
@@ -759,17 +780,20 @@
         }
 
         /**
-         * Sets the set of purposes for which the key can be used.
+         * Sets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+         * Attempts to use the key for any other purpose will be rejected.
          *
          * <p>This must be specified for all keys. There is no default.
          *
          * <p>If the set of purposes for which the key can be used does not contain
-         * {@link KeyStoreKeyProperties.Purpose#SIGN}, the self-signed certificate generated by
+         * {@link KeyStoreKeyProperties#PURPOSE_SIGN}, the self-signed certificate generated by
          * {@link KeyPairGenerator} of {@code AndroidKeyStore} provider will contain an invalid
          * signature. This is OK if the certificate is only used for obtaining the public key from
          * Android KeyStore.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
          */
         @NonNull
         public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) {
@@ -778,12 +802,15 @@
         }
 
         /**
-         * Sets the set of digests with which the key can be used when signing/verifying. Attempts
-         * to use the key with any other digest will be rejected.
+         * Sets the set of digests algorithms (e.g., {@code SHA-256}, {@code SHA-384}) with which
+         * the key can be used when signing/verifying. Attempts to use the key with any other digest
+         * algorithm will be rejected.
          *
          * <p>This must be specified for keys which are used for signing/verification.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
+         *
+         * @see KeyStoreKeyProperties.Digest
          */
         @NonNull
         public Builder setDigests(@KeyStoreKeyProperties.DigestEnum String... digests) {
@@ -792,13 +819,15 @@
         }
 
         /**
-         * Sets the set of padding schemes with which the key can be used when
-         * encrypting/decrypting. Attempts to use the key with any other padding scheme will be
-         * rejected.
+         * Sets the set of padding schemes (e.g., {@code OAEPPadding}, {@code PKCS1Padding},
+         * {@code NoPadding}) with which the key can be used when encrypting/decrypting. Attempts to
+         * use the key with any other padding scheme will be rejected.
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
          */
         @NonNull
         public Builder setEncryptionPaddings(
@@ -808,13 +837,15 @@
         }
 
         /**
-         * Sets the set of padding schemes with which the key can be used when
-         * signing/verifying. Attempts to use the key with any other padding scheme will be
-         * rejected.
+         * Sets the set of padding schemes (e.g., {@code PSS}, {@code PKCS#1}) with which the key
+         * can be used when signing/verifying. Attempts to use the key with any other padding scheme
+         * will be rejected.
          *
          * <p>This must be specified for RSA keys which are used for signing/verification.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code SIGNATURE_PADDING} constants.
          */
         @NonNull
         public Builder setSignaturePaddings(
@@ -824,12 +855,15 @@
         }
 
         /**
-         * Sets the set of block modes with which the key can be used when encrypting/decrypting.
-         * Attempts to use the key with any other block modes will be rejected.
+         * Sets the set of block modes (e.g., {@code ECB}, {@code CBC}, {@code CTR}) with which the
+         * key can be used when encrypting/decrypting. Attempts to use the key with any other block
+         * modes will be rejected.
          *
          * <p>This must be specified for encryption/decryption keys.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
          */
         @NonNull
         public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
@@ -857,7 +891,7 @@
          * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li>
          * </ul>
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          */
         @NonNull
         public Builder setRandomizedEncryptionRequired(boolean required) {
@@ -881,7 +915,7 @@
          * <p>This restriction applies only to private key operations. Public key operations are not
          * restricted.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          *
          * @see #setUserAuthenticationValidityDurationSeconds(int)
          */
@@ -900,7 +934,7 @@
          * <p>This restriction applies only to private key operations. Public key operations are not
          * restricted.
          *
-         * <p><b>NOTE: This has currently no effect.
+         * <p><b>NOTE: This has currently no effect.</b>
          *
          * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
          *        every use of the key.
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 3ed8899..7e3193d 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -131,10 +131,10 @@
         return mToken;
     }
 
-    static int getKeyTypeForAlgorithm(@KeyStoreKeyProperties.AlgorithmEnum String keyType) {
-        if (KeyStoreKeyProperties.Algorithm.RSA.equalsIgnoreCase(keyType)) {
+    static int getKeyTypeForAlgorithm(@KeyStoreKeyProperties.KeyAlgorithmEnum String keyType) {
+        if (KeyStoreKeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyType)) {
             return NativeConstants.EVP_PKEY_RSA;
-        } else if (KeyStoreKeyProperties.Algorithm.EC.equalsIgnoreCase(keyType)) {
+        } else if (KeyStoreKeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyType)) {
             return NativeConstants.EVP_PKEY_EC;
         } else {
             return -1;
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index bd601bc..4eeca47 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -496,7 +496,7 @@
         if ((mIv != null) && (mIv.length > 0)) {
             try {
                 AlgorithmParameters params =
-                        AlgorithmParameters.getInstance(KeyStoreKeyProperties.Algorithm.AES);
+                        AlgorithmParameters.getInstance(KeyStoreKeyProperties.KEY_ALGORITHM_AES);
                 params.init(new IvParameterSpec(mIv));
                 return params;
             } catch (NoSuchAlgorithmException e) {
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index 4b914c2..d734d66 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -174,7 +174,7 @@
                         spec.getEncryptionPaddings());
                 mKeymasterBlockModes =
                         KeyStoreKeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
-                if (((spec.getPurposes() & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
+                if (((spec.getPurposes() & KeyStoreKeyProperties.PURPOSE_ENCRYPT) != 0)
                         && (spec.isRandomizedEncryptionRequired())) {
                     for (int keymasterBlockMode : mKeymasterBlockModes) {
                         if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatible(
@@ -247,7 +247,7 @@
                 (spec.getKeyValidityForConsumptionEnd() != null)
                 ? spec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
 
-        if (((spec.getPurposes() & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
+        if (((spec.getPurposes() & KeyStoreKeyProperties.PURPOSE_ENCRYPT) != 0)
                 && (!spec.isRandomizedEncryptionRequired())) {
             // Permit caller-provided IV when encrypting with this key
             args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
@@ -265,9 +265,9 @@
             throw new ProviderException(
                     "Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
         }
-        String keyAlgorithmJCA;
+        @KeyStoreKeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA;
         try {
-            keyAlgorithmJCA = KeyStoreKeyProperties.Algorithm.fromKeymasterSecretKeyAlgorithm(
+            keyAlgorithmJCA = KeyStoreKeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
                     mKeymasterAlgorithm, mKeymasterDigest);
         } catch (IllegalArgumentException e) {
             throw new ProviderException("Failed to obtain JCA secret key algorithm name", e);
diff --git a/keystore/java/android/security/KeyStoreKeyProperties.java b/keystore/java/android/security/KeyStoreKeyProperties.java
index d1b0e5b..b58a7dd 100644
--- a/keystore/java/android/security/KeyStoreKeyProperties.java
+++ b/keystore/java/android/security/KeyStoreKeyProperties.java
@@ -26,95 +26,83 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.security.Key;
-import java.security.KeyFactory;
-import java.security.KeyPairGenerator;
 import java.util.Collection;
 import java.util.Locale;
 
-import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
-import javax.crypto.Mac;
-import javax.crypto.SecretKeyFactory;
-
 /**
  * Properties of {@code AndroidKeyStore} keys.
  */
 public abstract class KeyStoreKeyProperties {
     private KeyStoreKeyProperties() {}
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true,
-            value = {Purpose.ENCRYPT, Purpose.DECRYPT, Purpose.SIGN, Purpose.VERIFY})
+            value = {
+                PURPOSE_ENCRYPT,
+                PURPOSE_DECRYPT,
+                PURPOSE_SIGN,
+                PURPOSE_VERIFY,
+                })
     public @interface PurposeEnum {}
 
     /**
-     * Purposes of key.
+     * Purpose of key: encryption.
      */
-    public static abstract class Purpose {
+    public static final int PURPOSE_ENCRYPT = 1 << 0;
+
+    /**
+     * Purpose of key: decryption.
+     */
+    public static final int PURPOSE_DECRYPT = 1 << 1;
+
+    /**
+     * Purpose of key: signing or generating a Message Authentication Code (MAC).
+     */
+    public static final int PURPOSE_SIGN = 1 << 2;
+
+    /**
+     * Purpose of key: signature or Message Authentication Code (MAC) verification.
+     */
+    public static final int PURPOSE_VERIFY = 1 << 3;
+
+    static abstract class Purpose {
         private Purpose() {}
 
-        /**
-         * Purpose: encryption.
-         */
-        public static final int ENCRYPT = 1 << 0;
-
-        /**
-         * Purpose: decryption.
-         */
-        public static final int DECRYPT = 1 << 1;
-
-        /**
-         * Purpose: signing.
-         */
-        public static final int SIGN = 1 << 2;
-
-        /**
-         * Purpose: signature verification.
-         */
-        public static final int VERIFY = 1 << 3;
-
-        /**
-         * @hide
-         */
-        public static int toKeymaster(@PurposeEnum int purpose) {
+        static int toKeymaster(@PurposeEnum int purpose) {
             switch (purpose) {
-                case ENCRYPT:
+                case PURPOSE_ENCRYPT:
                     return KeymasterDefs.KM_PURPOSE_ENCRYPT;
-                case DECRYPT:
+                case PURPOSE_DECRYPT:
                     return KeymasterDefs.KM_PURPOSE_DECRYPT;
-                case SIGN:
+                case PURPOSE_SIGN:
                     return KeymasterDefs.KM_PURPOSE_SIGN;
-                case VERIFY:
+                case PURPOSE_VERIFY:
                     return KeymasterDefs.KM_PURPOSE_VERIFY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
         }
 
-        /**
-         * @hide
-         */
-        public static @PurposeEnum int fromKeymaster(int purpose) {
+        static @PurposeEnum int fromKeymaster(int purpose) {
             switch (purpose) {
                 case KeymasterDefs.KM_PURPOSE_ENCRYPT:
-                    return ENCRYPT;
+                    return PURPOSE_ENCRYPT;
                 case KeymasterDefs.KM_PURPOSE_DECRYPT:
-                    return DECRYPT;
+                    return PURPOSE_DECRYPT;
                 case KeymasterDefs.KM_PURPOSE_SIGN:
-                    return SIGN;
+                    return PURPOSE_SIGN;
                 case KeymasterDefs.KM_PURPOSE_VERIFY:
-                    return VERIFY;
+                    return PURPOSE_VERIFY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
-        public static int[] allToKeymaster(@PurposeEnum int purposes) {
+        static int[] allToKeymaster(@PurposeEnum int purposes) {
             int[] result = getSetFlags(purposes);
             for (int i = 0; i < result.length; i++) {
                 result[i] = toKeymaster(result[i]);
@@ -122,10 +110,7 @@
             return result;
         }
 
-        /**
-         * @hide
-         */
-        public static @PurposeEnum int allFromKeymaster(@NonNull Collection<Integer> purposes) {
+        static @PurposeEnum int allFromKeymaster(@NonNull Collection<Integer> purposes) {
             @PurposeEnum int result = 0;
             for (int keymasterPurpose : purposes) {
                 result |= fromKeymaster(keymasterPurpose);
@@ -134,59 +119,51 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @StringDef({
-        Algorithm.RSA,
-        Algorithm.EC,
-        Algorithm.AES,
-        Algorithm.HMAC_SHA1,
-        Algorithm.HMAC_SHA224,
-        Algorithm.HMAC_SHA256,
-        Algorithm.HMAC_SHA384,
-        Algorithm.HMAC_SHA512,
+        KEY_ALGORITHM_RSA,
+        KEY_ALGORITHM_EC,
+        KEY_ALGORITHM_AES,
+        KEY_ALGORITHM_HMAC_SHA1,
+        KEY_ALGORITHM_HMAC_SHA224,
+        KEY_ALGORITHM_HMAC_SHA256,
+        KEY_ALGORITHM_HMAC_SHA384,
+        KEY_ALGORITHM_HMAC_SHA512,
         })
-    public @interface AlgorithmEnum {}
+    public @interface KeyAlgorithmEnum {}
 
-    /**
-     * Key algorithms.
-     *
-     * <p>These are standard names which can be used to obtain instances of {@link KeyGenerator},
-     * {@link KeyPairGenerator}, {@link Cipher} (as part of the transformation string), {@link Mac},
-     * {@link KeyFactory}, {@link SecretKeyFactory}. These are also the names used by
-     * {@link Key#getAlgorithm()}.
-     */
-    public static abstract class Algorithm {
-        private Algorithm() {}
+    /** Rivest Shamir Adleman (RSA) key. */
+    public static final String KEY_ALGORITHM_RSA = "RSA";
 
-        /** Rivest Shamir Adleman (RSA) key. */
-        public static final String RSA = "RSA";
+    /** Elliptic Curve (EC) Cryptography key. */
+    public static final String KEY_ALGORITHM_EC = "EC";
 
-        /** Elliptic Curve (EC) key. */
-        public static final String EC = "EC";
+    /** Advanced Encryption Standard (AES) key. */
+    public static final String KEY_ALGORITHM_AES = "AES";
 
-        /** Advanced Encryption Standard (AES) key. */
-        public static final String AES = "AES";
+    /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-1 as the hash. */
+    public static final String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
 
-        /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-1 as the hash. */
-        public static final String HMAC_SHA1 = "HmacSHA1";
+    /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-224 as the hash. */
+    public static final String KEY_ALGORITHM_HMAC_SHA224 = "HmacSHA224";
 
-        /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-224 as the hash. */
-        public static final String HMAC_SHA224 = "HmacSHA224";
+    /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-256 as the hash. */
+    public static final String KEY_ALGORITHM_HMAC_SHA256 = "HmacSHA256";
 
-        /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-256 as the hash. */
-        public static final String HMAC_SHA256 = "HmacSHA256";
+    /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-384 as the hash. */
+    public static final String KEY_ALGORITHM_HMAC_SHA384 = "HmacSHA384";
 
-        /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-384 as the hash. */
-        public static final String HMAC_SHA384 = "HmacSHA384";
+    /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-512 as the hash. */
+    public static final String KEY_ALGORITHM_HMAC_SHA512 = "HmacSHA512";
 
-        /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-512 as the hash. */
-        public static final String HMAC_SHA512 = "HmacSHA512";
+    static abstract class KeyAlgorithm {
+        private KeyAlgorithm() {}
 
-        /**
-         * @hide
-         */
-        static int toKeymasterSecretKeyAlgorithm(@NonNull @AlgorithmEnum String algorithm) {
-            if (AES.equalsIgnoreCase(algorithm)) {
+        static int toKeymasterSecretKeyAlgorithm(@NonNull @KeyAlgorithmEnum String algorithm) {
+            if (KEY_ALGORITHM_AES.equalsIgnoreCase(algorithm)) {
                 return KeymasterDefs.KM_ALGORITHM_AES;
             } else if (algorithm.toUpperCase(Locale.US).startsWith("HMAC")) {
                 return KeymasterDefs.KM_ALGORITHM_HMAC;
@@ -196,11 +173,8 @@
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
-        static @AlgorithmEnum String fromKeymasterSecretKeyAlgorithm(
+        static @KeyAlgorithmEnum String fromKeymasterSecretKeyAlgorithm(
                 int keymasterAlgorithm, int keymasterDigest) {
             switch (keymasterAlgorithm) {
                 case KeymasterDefs.KM_ALGORITHM_AES:
@@ -208,26 +182,26 @@
                         throw new IllegalArgumentException("Digest not supported for AES key: "
                                 + Digest.fromKeymaster(keymasterDigest));
                     }
-                    return AES;
+                    return KEY_ALGORITHM_AES;
                 case KeymasterDefs.KM_ALGORITHM_HMAC:
                     switch (keymasterDigest) {
                         case KeymasterDefs.KM_DIGEST_SHA1:
-                            return HMAC_SHA1;
+                            return KEY_ALGORITHM_HMAC_SHA1;
                         case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                            return HMAC_SHA224;
+                            return KEY_ALGORITHM_HMAC_SHA224;
                         case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                            return HMAC_SHA256;
+                            return KEY_ALGORITHM_HMAC_SHA256;
                         case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                            return HMAC_SHA384;
+                            return KEY_ALGORITHM_HMAC_SHA384;
                         case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                            return HMAC_SHA512;
+                            return KEY_ALGORITHM_HMAC_SHA512;
                         default:
                             throw new IllegalArgumentException("Unsupported HMAC digest: "
                                     + Digest.fromKeymaster(keymasterDigest));
                     }
                 default:
                     throw new IllegalArgumentException(
-                            "Unsupported algorithm: " + keymasterAlgorithm);
+                            "Unsupported key algorithm: " + keymasterAlgorithm);
             }
         }
 
@@ -236,7 +210,7 @@
          *
          * @return keymaster digest or {@code -1} if the algorithm does not involve a digest.
          */
-        static int toKeymasterDigest(@NonNull @AlgorithmEnum String algorithm) {
+        static int toKeymasterDigest(@NonNull @KeyAlgorithmEnum String algorithm) {
             String algorithmUpper = algorithm.toUpperCase(Locale.US);
             if (algorithmUpper.startsWith("HMAC")) {
                 String digestUpper = algorithmUpper.substring("HMAC".length());
@@ -261,72 +235,63 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @StringDef({
-        BlockMode.ECB,
-        BlockMode.CBC,
-        BlockMode.CTR,
-        BlockMode.GCM,
+        BLOCK_MODE_ECB,
+        BLOCK_MODE_CBC,
+        BLOCK_MODE_CTR,
+        BLOCK_MODE_GCM,
         })
     public @interface BlockModeEnum {}
 
-    /**
-     * Block modes that can be used when encrypting/decrypting using a key.
-     */
-    public static abstract class BlockMode {
+    /** Electronic Codebook (ECB) block mode. */
+    public static final String BLOCK_MODE_ECB = "ECB";
+
+    /** Cipher Block Chaining (CBC) block mode. */
+    public static final String BLOCK_MODE_CBC = "CBC";
+
+    /** Counter (CTR) block mode. */
+    public static final String BLOCK_MODE_CTR = "CTR";
+
+    /** Galois/Counter Mode (GCM) block mode. */
+    public static final String BLOCK_MODE_GCM = "GCM";
+
+    static abstract class BlockMode {
         private BlockMode() {}
 
-        /** Electronic Codebook (ECB) block mode. */
-        public static final String ECB = "ECB";
-
-        /** Cipher Block Chaining (CBC) block mode. */
-        public static final String CBC = "CBC";
-
-        /** Counter (CTR) block mode. */
-        public static final String CTR = "CTR";
-
-        /** Galois/Counter Mode (GCM) block mode. */
-        public static final String GCM = "GCM";
-
-        /**
-         * @hide
-         */
         static int toKeymaster(@NonNull @BlockModeEnum String blockMode) {
-            if (ECB.equalsIgnoreCase(blockMode)) {
+            if (BLOCK_MODE_ECB.equalsIgnoreCase(blockMode)) {
                 return KeymasterDefs.KM_MODE_ECB;
-            } else if (CBC.equalsIgnoreCase(blockMode)) {
+            } else if (BLOCK_MODE_CBC.equalsIgnoreCase(blockMode)) {
                 return KeymasterDefs.KM_MODE_CBC;
-            } else if (CTR.equalsIgnoreCase(blockMode)) {
+            } else if (BLOCK_MODE_CTR.equalsIgnoreCase(blockMode)) {
                 return KeymasterDefs.KM_MODE_CTR;
-            } else if (GCM.equalsIgnoreCase(blockMode)) {
+            } else if (BLOCK_MODE_GCM.equalsIgnoreCase(blockMode)) {
                 return KeymasterDefs.KM_MODE_GCM;
             } else {
                 throw new IllegalArgumentException("Unsupported block mode: " + blockMode);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static @BlockModeEnum String fromKeymaster(int blockMode) {
             switch (blockMode) {
                 case KeymasterDefs.KM_MODE_ECB:
-                    return ECB;
+                    return BLOCK_MODE_ECB;
                 case KeymasterDefs.KM_MODE_CBC:
-                    return CBC;
+                    return BLOCK_MODE_CBC;
                 case KeymasterDefs.KM_MODE_CTR:
-                    return CTR;
+                    return BLOCK_MODE_CTR;
                 case KeymasterDefs.KM_MODE_GCM:
-                    return GCM;
+                    return BLOCK_MODE_GCM;
                 default:
                     throw new IllegalArgumentException("Unsupported block mode: " + blockMode);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static @BlockModeEnum String[] allFromKeymaster(@NonNull Collection<Integer> blockModes) {
             if ((blockModes == null) || (blockModes.isEmpty())) {
@@ -341,9 +306,6 @@
             return result;
         }
 
-        /**
-         * @hide
-         */
         static int[] allToKeymaster(@Nullable @BlockModeEnum String[] blockModes) {
             if ((blockModes == null) || (blockModes.length == 0)) {
                 return EmptyArray.INT;
@@ -356,52 +318,49 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @StringDef({
-        EncryptionPadding.NONE,
-        EncryptionPadding.PKCS7,
-        EncryptionPadding.RSA_PKCS1,
-        EncryptionPadding.RSA_OAEP,
+        ENCRYPTION_PADDING_NONE,
+        ENCRYPTION_PADDING_PKCS7,
+        ENCRYPTION_PADDING_RSA_PKCS1,
+        ENCRYPTION_PADDING_RSA_OAEP,
         })
     public @interface EncryptionPaddingEnum {}
 
     /**
-     * Padding schemes for encryption/decryption.
+     * No encryption padding.
      */
-    public static abstract class EncryptionPadding {
+    public static final String ENCRYPTION_PADDING_NONE = "NoPadding";
+
+    /**
+     * PKCS#7 encryption padding scheme.
+     */
+    public static final String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
+
+    /**
+     * RSA PKCS#1 v1.5 padding scheme for encryption.
+     */
+    public static final String ENCRYPTION_PADDING_RSA_PKCS1 = "PKCS1Padding";
+
+    /**
+     * RSA Optimal Asymmetric Encryption Padding (OAEP) scheme.
+     */
+    public static final String ENCRYPTION_PADDING_RSA_OAEP = "OAEPPadding";
+
+    static abstract class EncryptionPadding {
         private EncryptionPadding() {}
 
-        /**
-         * No padding.
-         */
-        public static final String NONE = "NoPadding";
-
-        /**
-         * PKCS#7 padding.
-         */
-        public static final String PKCS7 = "PKCS7Padding";
-
-        /**
-         * RSA PKCS#1 v1.5 padding for encryption/decryption.
-         */
-        public static final String RSA_PKCS1 = "PKCS1Padding";
-
-        /**
-         * RSA Optimal Asymmetric Encryption Padding (OAEP).
-         */
-        public static final String RSA_OAEP = "OAEPPadding";
-
-        /**
-         * @hide
-         */
         static int toKeymaster(@NonNull @EncryptionPaddingEnum String padding) {
-            if (NONE.equalsIgnoreCase(padding)) {
+            if (ENCRYPTION_PADDING_NONE.equalsIgnoreCase(padding)) {
                 return KeymasterDefs.KM_PAD_NONE;
-            } else if (PKCS7.equalsIgnoreCase(padding)) {
+            } else if (ENCRYPTION_PADDING_PKCS7.equalsIgnoreCase(padding)) {
                 return KeymasterDefs.KM_PAD_PKCS7;
-            } else if (RSA_PKCS1.equalsIgnoreCase(padding)) {
+            } else if (ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(padding)) {
                 return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
-            } else if (RSA_OAEP.equalsIgnoreCase(padding)) {
+            } else if (ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(padding)) {
                 return KeymasterDefs.KM_PAD_RSA_OAEP;
             } else {
                 throw new IllegalArgumentException(
@@ -409,29 +368,23 @@
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static @EncryptionPaddingEnum String fromKeymaster(int padding) {
             switch (padding) {
                 case KeymasterDefs.KM_PAD_NONE:
-                    return NONE;
+                    return ENCRYPTION_PADDING_NONE;
                 case KeymasterDefs.KM_PAD_PKCS7:
-                    return PKCS7;
+                    return ENCRYPTION_PADDING_PKCS7;
                 case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
-                    return RSA_PKCS1;
+                    return ENCRYPTION_PADDING_RSA_PKCS1;
                 case KeymasterDefs.KM_PAD_RSA_OAEP:
-                    return RSA_OAEP;
+                    return ENCRYPTION_PADDING_RSA_OAEP;
                 default:
                     throw new IllegalArgumentException(
                             "Unsupported encryption padding: " + padding);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static int[] allToKeymaster(@Nullable @EncryptionPaddingEnum String[] paddings) {
             if ((paddings == null) || (paddings.length == 0)) {
@@ -445,37 +398,34 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @StringDef({
-        SignaturePadding.RSA_PKCS1,
-        SignaturePadding.RSA_PSS,
+        SIGNATURE_PADDING_RSA_PKCS1,
+        SIGNATURE_PADDING_RSA_PSS,
         })
     public @interface SignaturePaddingEnum {}
 
     /**
-     * Padding schemes for signing/verification.
+     * RSA PKCS#1 v1.5 padding for signatures.
      */
-    public static abstract class SignaturePadding {
+    public static final String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
+
+    /**
+     * RSA PKCS#1 v2.1 Probabilistic Signature Scheme (PSS) padding.
+     */
+    public static final String SIGNATURE_PADDING_RSA_PSS = "PSS";
+
+    static abstract class SignaturePadding {
         private SignaturePadding() {}
 
-        /**
-         * RSA PKCS#1 v1.5 padding for signatures.
-         */
-        public static final String RSA_PKCS1 = "PKCS1";
-
-        /**
-         * RSA PKCS#1 v2.1 Probabilistic Signature Scheme (PSS) padding.
-         */
-        public static final String RSA_PSS = "PSS";
-
-        /**
-         * @hide
-         */
         static int toKeymaster(@NonNull @SignaturePaddingEnum String padding) {
             switch (padding.toUpperCase(Locale.US)) {
-                case RSA_PKCS1:
+                case SIGNATURE_PADDING_RSA_PKCS1:
                     return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN;
-                case RSA_PSS:
+                case SIGNATURE_PADDING_RSA_PSS:
                     return KeymasterDefs.KM_PAD_RSA_PSS;
                 default:
                     throw new IllegalArgumentException(
@@ -483,24 +433,18 @@
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static @SignaturePaddingEnum String fromKeymaster(int padding) {
             switch (padding) {
                 case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN:
-                    return RSA_PKCS1;
+                    return SIGNATURE_PADDING_RSA_PKCS1;
                 case KeymasterDefs.KM_PAD_RSA_PSS:
-                    return RSA_PSS;
+                    return SIGNATURE_PADDING_RSA_PSS;
                 default:
                     throw new IllegalArgumentException("Unsupported signature padding: " + padding);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static int[] allToKeymaster(@Nullable @SignaturePaddingEnum String[] paddings) {
             if ((paddings == null) || (paddings.length == 0)) {
@@ -514,112 +458,102 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @StringDef({
-        Digest.NONE,
-        Digest.MD5,
-        Digest.SHA1,
-        Digest.SHA224,
-        Digest.SHA256,
-        Digest.SHA384,
-        Digest.SHA512,
+        DIGEST_NONE,
+        DIGEST_MD5,
+        DIGEST_SHA1,
+        DIGEST_SHA224,
+        DIGEST_SHA256,
+        DIGEST_SHA384,
+        DIGEST_SHA512,
         })
     public @interface DigestEnum {}
 
     /**
-     * Digests that can be used with a key when signing or generating Message Authentication
-     * Codes (MACs).
+     * No digest: sign/authenticate the raw message.
      */
-    public static abstract class Digest {
+    public static final String DIGEST_NONE = "NONE";
+
+    /**
+     * MD5 digest.
+     */
+    public static final String DIGEST_MD5 = "MD5";
+
+    /**
+     * SHA-1 digest.
+     */
+    public static final String DIGEST_SHA1 = "SHA-1";
+
+    /**
+     * SHA-2 224 (aka SHA-224) digest.
+     */
+    public static final String DIGEST_SHA224 = "SHA-224";
+
+    /**
+     * SHA-2 256 (aka SHA-256) digest.
+     */
+    public static final String DIGEST_SHA256 = "SHA-256";
+
+    /**
+     * SHA-2 384 (aka SHA-384) digest.
+     */
+    public static final String DIGEST_SHA384 = "SHA-384";
+
+    /**
+     * SHA-2 512 (aka SHA-512) digest.
+     */
+    public static final String DIGEST_SHA512 = "SHA-512";
+
+    static abstract class Digest {
         private Digest() {}
 
-        /**
-         * No digest: sign/authenticate the raw message.
-         */
-        public static final String NONE = "NONE";
-
-        /**
-         * MD5 digest.
-         */
-        public static final String MD5 = "MD5";
-
-        /**
-         * SHA-1 digest.
-         */
-        public static final String SHA1 = "SHA-1";
-
-        /**
-         * SHA-2 224 (aka SHA-224) digest.
-         */
-        public static final String SHA224 = "SHA-224";
-
-        /**
-         * SHA-2 256 (aka SHA-256) digest.
-         */
-        public static final String SHA256 = "SHA-256";
-
-        /**
-         * SHA-2 384 (aka SHA-384) digest.
-         */
-        public static final String SHA384 = "SHA-384";
-
-        /**
-         * SHA-2 512 (aka SHA-512) digest.
-         */
-        public static final String SHA512 = "SHA-512";
-
-        /**
-         * @hide
-         */
         static int toKeymaster(@NonNull @DigestEnum String digest) {
             switch (digest.toUpperCase(Locale.US)) {
-                case SHA1:
+                case DIGEST_SHA1:
                     return KeymasterDefs.KM_DIGEST_SHA1;
-                case SHA224:
+                case DIGEST_SHA224:
                     return KeymasterDefs.KM_DIGEST_SHA_2_224;
-                case SHA256:
+                case DIGEST_SHA256:
                     return KeymasterDefs.KM_DIGEST_SHA_2_256;
-                case SHA384:
+                case DIGEST_SHA384:
                     return KeymasterDefs.KM_DIGEST_SHA_2_384;
-                case SHA512:
+                case DIGEST_SHA512:
                     return KeymasterDefs.KM_DIGEST_SHA_2_512;
-                case NONE:
+                case DIGEST_NONE:
                     return KeymasterDefs.KM_DIGEST_NONE;
-                case MD5:
+                case DIGEST_MD5:
                     return KeymasterDefs.KM_DIGEST_MD5;
                 default:
                     throw new IllegalArgumentException("Unsupported digest algorithm: " + digest);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static @DigestEnum String fromKeymaster(int digest) {
             switch (digest) {
                 case KeymasterDefs.KM_DIGEST_NONE:
-                    return NONE;
+                    return DIGEST_NONE;
                 case KeymasterDefs.KM_DIGEST_MD5:
-                    return MD5;
+                    return DIGEST_MD5;
                 case KeymasterDefs.KM_DIGEST_SHA1:
-                    return SHA1;
+                    return DIGEST_SHA1;
                 case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                    return SHA224;
+                    return DIGEST_SHA224;
                 case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                    return SHA256;
+                    return DIGEST_SHA256;
                 case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                    return SHA384;
+                    return DIGEST_SHA384;
                 case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                    return SHA512;
+                    return DIGEST_SHA512;
                 default:
                     throw new IllegalArgumentException("Unsupported digest algorithm: " + digest);
             }
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static @DigestEnum String[] allFromKeymaster(@NonNull Collection<Integer> digests) {
             if (digests.isEmpty()) {
@@ -634,9 +568,6 @@
             return result;
         }
 
-        /**
-         * @hide
-         */
         @NonNull
         static int[] allToKeymaster(@Nullable @DigestEnum String[] digests) {
             if ((digests == null) || (digests.length == 0)) {
@@ -652,39 +583,40 @@
         }
     }
 
+    /**
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({Origin.GENERATED, Origin.IMPORTED, Origin.UNKNOWN})
+    @IntDef({
+        ORIGIN_GENERATED,
+        ORIGIN_IMPORTED,
+        ORIGIN_UNKNOWN,
+        })
     public @interface OriginEnum {}
 
+    /** Key was generated inside AndroidKeyStore. */
+    public static final int ORIGIN_GENERATED = 1 << 0;
+
+    /** Key was imported into AndroidKeyStore. */
+    public static final int ORIGIN_IMPORTED = 1 << 1;
+
     /**
-     * Origin of the key.
+     * Origin of the key is unknown. This can occur only for keys backed by an old TEE-backed
+     * implementation which does not record origin information.
      */
-    public static abstract class Origin {
+    public static final int ORIGIN_UNKNOWN = 1 << 2;
+
+    static abstract class Origin {
         private Origin() {}
 
-        /** Key was generated inside AndroidKeyStore. */
-        public static final int GENERATED = 1 << 0;
-
-        /** Key was imported into AndroidKeyStore. */
-        public static final int IMPORTED = 1 << 1;
-
-        /**
-         * Origin of the key is unknown. This can occur only for keys backed by an old TEE-backed
-         * implementation which does not record origin information.
-         */
-        public static final int UNKNOWN = 1 << 2;
-
-        /**
-         * @hide
-         */
-        public static @OriginEnum int fromKeymaster(int origin) {
+        static @OriginEnum int fromKeymaster(int origin) {
             switch (origin) {
                 case KeymasterDefs.KM_ORIGIN_GENERATED:
-                    return GENERATED;
+                    return ORIGIN_GENERATED;
                 case KeymasterDefs.KM_ORIGIN_IMPORTED:
-                    return IMPORTED;
+                    return ORIGIN_IMPORTED;
                 case KeymasterDefs.KM_ORIGIN_UNKNOWN:
-                    return UNKNOWN;
+                    return ORIGIN_UNKNOWN;
                 default:
                     throw new IllegalArgumentException("Unknown origin: " + origin);
             }
diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java
index 81a19bb..4c43f89 100644
--- a/keystore/java/android/security/KeyStoreKeySpec.java
+++ b/keystore/java/android/security/KeyStoreKeySpec.java
@@ -135,7 +135,7 @@
     }
 
     /**
-     * Gets the origin of the key.
+     * Gets the origin of the key. See {@link KeyStoreKeyProperties}.{@code ORIGIN} constants.
      */
     public @KeyStoreKeyProperties.OriginEnum int getOrigin() {
         return mOrigin;
@@ -179,14 +179,21 @@
     }
 
     /**
-     * Gets the set of purposes for which the key can be used.
+     * Gets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+     * Attempts to use the key for any other purpose will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
      */
     public @KeyStoreKeyProperties.PurposeEnum int getPurposes() {
         return mPurposes;
     }
 
     /**
-     * Gets the set of block modes with which the key can be used.
+     * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+     * when encrypting/decrypting. Attempts to use the key with any other block modes will be
+     * rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
@@ -194,7 +201,11 @@
     }
 
     /**
-     * Gets the set of padding modes with which the key can be used when encrypting/decrypting.
+     * Gets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code PKCS1Padding},
+     * {@code NoPadding}) with which the key can be used when encrypting/decrypting. Attempts to use
+     * the key with any other padding scheme will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
@@ -202,7 +213,11 @@
     }
 
     /**
-     * Gets the set of padding modes with which the key can be used when signing/verifying.
+     * Gets the set of padding schemes (e.g., {@code PSS}, {@code PKCS#1}) with which the key
+     * can be used when signing/verifying. Attempts to use the key with any other padding scheme
+     * will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code SIGNATURE_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
@@ -210,7 +225,10 @@
     }
 
     /**
-     * Gets the set of digest algorithms with which the key can be used.
+     * Gets the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384}) with which the key
+     * can be used.
+     *
+     * @see KeyStoreKeyProperties.Digest
      */
     @NonNull
     public @KeyStoreKeyProperties.DigestEnum String[] getDigests() {
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index 4a736c3..a7fab80 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -62,11 +62,11 @@
  *         "key1",
  *         new KeyStore.SecretKeyEntry(key),
  *         new KeyStoreParameter.Builder(context)
- *                 .setPurposes(KeyStoreKeyProperties.Purpose.ENCRYPT
- *                         | KeyStoreKeyProperties.Purpose.DECRYPT)
- *                 .setBlockMode(KeyStoreKeyProperties.BlockMode.CBC)
+ *                 .setPurposes(KeyStoreKeyProperties.PURPOSE_ENCRYPT
+ *                         | KeyStoreKeyProperties.PURPOSE_DECRYPT)
+ *                 .setBlockMode(KeyStoreKeyProperties.BLOCK_MODE_CBC)
  *                 .setEncryptionPaddings(
- *                         KeyStoreKeyProperties.EncryptionPaddings.PKCS7)
+ *                         KeyStoreKeyProperties.ENCRYPTION_PADDING_PKCS7)
  *                 .build());
  * // Key imported, obtain a reference to it.
  * SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
@@ -90,8 +90,8 @@
  *         "key2",
  *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
  *         new KeyStoreParameter.Builder(context)
- *                 .setPurposes(KeyStoreKeyProperties.Purpose.SIGN)
- *                 .setDigests(KeyStoreKeyProperties.Digest.SHA256)
+ *                 .setPurposes(KeyStoreKeyProperties.PURPOSE_SIGN)
+ *                 .setDigests(KeyStoreKeyProperties.DIGEST_SHA256)
  *                 // Only permit this key to be used if the user
  *                 // authenticated within the last ten minutes.
  *                 .setUserAuthenticationRequired(true)
@@ -211,14 +211,21 @@
     }
 
     /**
-     * Gets the set of purposes for which the key can be used.
+     * Gets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+     * Attempts to use the key for any other purpose will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
      */
     public @KeyStoreKeyProperties.PurposeEnum int getPurposes() {
         return mPurposes;
     }
 
     /**
-     * Gets the set of padding schemes with which the key can be used when encrypting/decrypting.
+     * Gets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code PKCS1Padding},
+     * {@code NoPadding}) with which the key can be used when encrypting/decrypting. Attempts to use
+     * the key with any other padding scheme will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
@@ -226,8 +233,11 @@
     }
 
     /**
-     * Gets the set of padding schemes with which the key can be used when signing or verifying
-     * signatures.
+     * Gets the set of padding schemes (e.g., {@code PSS}, {@code PKCS#1}) with which the key
+     * can be used when signing/verifying. Attempts to use the key with any other padding scheme
+     * will be rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code SIGNATURE_PADDING} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
@@ -235,11 +245,13 @@
     }
 
     /**
-     * Gets the set of digest algorithms with which the key can be used.
+     * Gets the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384}) with which the key
+     * can be used.
      *
      * @throws IllegalStateException if this set has not been specified.
      *
      * @see #isDigestsSpecified()
+     * @see KeyStoreKeyProperties.Digest
      */
     @NonNull
     public @KeyStoreKeyProperties.DigestEnum String[] getDigests() {
@@ -261,7 +273,11 @@
     }
 
     /**
-     * Gets the set of block modes with which the key can be used.
+     * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+     * when encrypting/decrypting. Attempts to use the key with any other block modes will be
+     * rejected.
+     *
+     * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
      */
     @NonNull
     public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
@@ -376,7 +392,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          *
          * @see #setKeyValidityEnd(Date)
          */
@@ -391,7 +407,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          *
          * @see #setKeyValidityStart(Date)
          * @see #setKeyValidityForConsumptionEnd(Date)
@@ -409,7 +425,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          *
          * @see #setKeyValidityForConsumptionEnd(Date)
          */
@@ -425,7 +441,7 @@
          *
          * <p>By default, the key is valid at any instant.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          *
          * @see #setKeyValidityForOriginationEnd(Date)
          */
@@ -436,11 +452,14 @@
         }
 
         /**
-         * Sets the set of purposes for which the key can be used.
+         * Sets the set of purposes (e.g., encrypt, decrypt, sign) for which the key can be used.
+         * Attempts to use the key for any other purpose will be rejected.
          *
          * <p>This must be specified for all keys. There is no default.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code PURPOSE} flags.
          */
         @NonNull
         public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) {
@@ -449,13 +468,15 @@
         }
 
         /**
-         * Sets the set of padding schemes with which the key can be used when
-         * encrypting/decrypting. Attempts to use the key with any other padding scheme will be
-         * rejected.
+         * Sets the set of padding schemes (e.g., {@code OAEPPadding}, {@code PKCS7Padding},
+         * {@code NoPadding}) with which the key can be used when encrypting/decrypting. Attempts to
+         * use the key with any other padding scheme will be rejected.
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code ENCRYPTION_PADDING} constants.
          */
         @NonNull
         public Builder setEncryptionPaddings(
@@ -465,13 +486,15 @@
         }
 
         /**
-         * Sets the set of padding schemes with which the key can be used when
-         * signing/verifying. Attempts to use the key with any other padding scheme will be
-         * rejected.
+         * Sets the set of padding schemes (e.g., {@code PSS}, {@code PKCS#1}) with which the key
+         * can be used when signing/verifying. Attempts to use the key with any other padding scheme
+         * will be rejected.
          *
          * <p>This must be specified for RSA keys which are used for signing/verification.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code SIGNATURE_PADDING} constants.
          */
         @NonNull
         public Builder setSignaturePaddings(
@@ -482,13 +505,17 @@
 
 
         /**
-         * Sets the set of digests with which the key can be used when signing/verifying or
-         * generating MACs. Attempts to use the key with any other digest will be rejected.
+         * Sets the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384}) with which the
+         * key can be used when signing/verifying or generating MACs. Attempts to use the key with
+         * any other digest algorithm will be rejected.
          *
-         * <p>For HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()}. For
-         * asymmetric signing keys this constraint must be specified.
+         * <p>For HMAC keys, the default is the digest algorithm specified in
+         * {@link Key#getAlgorithm()}. For asymmetric signing keys the set of digest algorithms
+         * must be specified.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
+         *
+         * @see KeyStoreKeyProperties.Digest
          */
         @NonNull
         public Builder setDigests(@KeyStoreKeyProperties.DigestEnum String... digests) {
@@ -497,12 +524,15 @@
         }
 
         /**
-         * Sets the set of block modes with which the key can be used when encrypting/decrypting.
-         * Attempts to use the key with any other block modes will be rejected.
+         * Sets the set of block modes (e.g., {@code CBC}, {@code CTR}, {@code ECB}) with which the
+         * key can be used when encrypting/decrypting. Attempts to use the key with any other block
+         * modes will be rejected.
          *
          * <p>This must be specified for encryption/decryption keys.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
+         *
+         * <p>See {@link KeyStoreKeyProperties}.{@code BLOCK_MODE} constants.
          */
         @NonNull
         public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
@@ -544,7 +574,7 @@
          * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li>
          * </ul>
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          */
         @NonNull
         public Builder setRandomizedEncryptionRequired(boolean required) {
@@ -565,7 +595,7 @@
          * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
          * information</a>.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          *
          * @see #setUserAuthenticationValidityDurationSeconds(int)
          */
@@ -581,7 +611,7 @@
          *
          * <p>By default, the user needs to authenticate for every use of the key.
          *
-         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.</b>
          *
          * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
          *        every use of the key.
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 74964f6..8f5fea3 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -142,7 +142,7 @@
     char property[PROPERTY_VALUE_MAX];
     if (property_get(PROPERTY_PATH_CACHE_SIZE, property, nullptr) > 0) {
         INIT_LOGD("  Setting %s cache size to %sMB", name, property);
-        setMaxSize(MB(atof(property)));
+        mMaxSize = MB(atof(property));
     } else {
         INIT_LOGD("  Using default %s cache size of %.2fMB", name, DEFAULT_PATH_CACHE_SIZE);
     }
@@ -172,13 +172,6 @@
     return mMaxSize;
 }
 
-void PathCache::setMaxSize(uint32_t maxSize) {
-    mMaxSize = maxSize;
-    while (mSize > mMaxSize) {
-        mCache.removeOldest();
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Callbacks
 ///////////////////////////////////////////////////////////////////////////////
@@ -267,24 +260,18 @@
         PathTexture* texture, bool addToCache) {
     generateTexture(*bitmap, texture);
 
+    // Note here that we upload to a texture even if it's bigger than mMaxSize.
+    // Such an entry in mCache will only be temporary, since it will be evicted
+    // immediately on trim, or on any other Path entering the cache.
     uint32_t size = texture->width * texture->height;
-    if (size < mMaxSize) {
-        mSize += size;
-        PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d",
-                texture->id, size, mSize);
-        if (mDebugEnabled) {
-            ALOGD("Shape created, size = %d", size);
-        }
-        if (addToCache) {
-            mCache.put(entry, texture);
-        }
-    } else {
-        // It's okay to add a texture that's bigger than the cache since
-        // we'll trim the cache later when addToCache is set to false
-        if (!addToCache) {
-            mSize += size;
-        }
-        texture->cleanup = true;
+    mSize += size;
+    PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d",
+            texture->id, size, mSize);
+    if (mDebugEnabled) {
+        ALOGD("Shape created, size = %d", size);
+    }
+    if (addToCache) {
+        mCache.put(entry, texture);
     }
 }
 
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 4297693..7014863 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -186,10 +186,6 @@
     void clear();
 
     /**
-     * Sets the maximum size of the cache in bytes.
-     */
-    void setMaxSize(uint32_t maxSize);
-    /**
      * Returns the maximum size of the cache in bytes.
      */
     uint32_t getMaxSize();
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index cb5560f..e993f74 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -250,7 +250,7 @@
 #define DEFAULT_TEXTURE_CACHE_SIZE 24.0f
 #define DEFAULT_LAYER_CACHE_SIZE 16.0f
 #define DEFAULT_RENDER_BUFFER_CACHE_SIZE 2.0f
-#define DEFAULT_PATH_CACHE_SIZE 10.0f
+#define DEFAULT_PATH_CACHE_SIZE 4.0f
 #define DEFAULT_VERTEX_CACHE_SIZE 1.0f
 #define DEFAULT_PATCH_CACHE_SIZE 128 // in kB
 #define DEFAULT_GRADIENT_CACHE_SIZE 0.5f
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index a721923..ac59ace 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -43,6 +43,8 @@
 
     public abstract int getVolumeControllerUid();
 
+    public abstract void updateRingerModeAffectedStreamsInternal();
+
     public interface RingerModeDelegate {
         /** Called when external ringer mode is evaluated, returns the new internal ringer mode */
         int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
@@ -53,5 +55,7 @@
                 int ringerModeExternal, VolumePolicy policy);
 
         boolean canVolumeDownEnterSilent();
+
+        int getRingerModeAffectedStreams(int streams);
     }
 }
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index b7ef95c..d9e554c 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -49,7 +49,7 @@
  * sync.setAudioTrack(audioTrack);
  * sync.setCallback(new MediaSync.Callback() {
  *     {@literal @Override}
- *     public void onAudioBufferConsumed(MediaSync sync, ByteBuffer audioBuffer, int bufferIndex) {
+ *     public void onAudioBufferConsumed(MediaSync sync, ByteBuffer audioBuffer, int bufferId) {
  *         ...
  *     }
  * }, null);
@@ -62,8 +62,8 @@
  *   // videoDecoder.releaseOutputBuffer(videoOutputBufferIx, videoPresentationTimeNs);
  *   // More details are available as below.
  *   ...
- *   sync.queueAudio(audioByteBuffer, bufferIndex, audioPresentationTimeUs); // non-blocking.
- *   // The audioByteBuffer and bufferIndex will be returned via callback.
+ *   sync.queueAudio(audioByteBuffer, bufferId, audioPresentationTimeUs); // non-blocking.
+ *   // The audioByteBuffer and bufferId will be returned via callback.
  *   // More details are available as below.
  *   ...
  *     ...
@@ -75,22 +75,22 @@
  * // The following code snippet illustrates how video/audio raw frames are created by
  * // MediaCodec's, how they are fed to MediaSync and how they are returned by MediaSync.
  * // This is the callback from MediaCodec.
- * onOutputBufferAvailable(MediaCodec codec, int bufferIndex, BufferInfo info) {
+ * onOutputBufferAvailable(MediaCodec codec, int bufferId, BufferInfo info) {
  *     // ...
  *     if (codec == videoDecoder) {
  *         // surface timestamp must contain media presentation time in nanoseconds.
- *         codec.releaseOutputBuffer(bufferIndex, 1000 * info.presentationTime);
+ *         codec.releaseOutputBuffer(bufferId, 1000 * info.presentationTime);
  *     } else {
- *         ByteBuffer audioByteBuffer = codec.getOutputBuffer(bufferIndex);
- *         sync.queueByteBuffer(audioByteBuffer, bufferIndex, info.size, info.presentationTime);
+ *         ByteBuffer audioByteBuffer = codec.getOutputBuffer(bufferId);
+ *         sync.queueByteBuffer(audioByteBuffer, bufferId, info.size, info.presentationTime);
  *     }
  *     // ...
  * }
  *
  * // This is the callback from MediaSync.
- * onAudioBufferConsumed(MediaSync sync, ByteBuffer buffer, int bufferIndex) {
+ * onAudioBufferConsumed(MediaSync sync, ByteBuffer buffer, int bufferId) {
  *     // ...
- *     audioDecoder.releaseBuffer(bufferIndex, false);
+ *     audioDecoder.releaseBuffer(bufferId, false);
  *     // ...
  * }
  *
@@ -123,10 +123,11 @@
          *
          * @param sync The MediaSync object.
          * @param audioBuffer The returned audio buffer.
-         * @param bufferIndex The index associated with the audio buffer
+         * @param bufferId The ID associated with audioBuffer as passed into
+         *     {@link MediaSync#queueAudio}.
          */
         public abstract void onAudioBufferConsumed(
-                @NonNull MediaSync sync, @NonNull ByteBuffer audioBuffer, int bufferIndex);
+                @NonNull MediaSync sync, @NonNull ByteBuffer audioBuffer, int bufferId);
     }
 
     /** Audio track failed.
@@ -172,10 +173,10 @@
         public int mBufferIndex;
         long mPresentationTimeUs;
 
-        public AudioBuffer(@NonNull ByteBuffer byteBuffer, int bufferIndex,
+        public AudioBuffer(@NonNull ByteBuffer byteBuffer, int bufferId,
                            long presentationTimeUs) {
             mByteBuffer = byteBuffer;
-            mBufferIndex = bufferIndex;
+            mBufferIndex = bufferId;
             mPresentationTimeUs = presentationTimeUs;
         }
     }
@@ -563,22 +564,23 @@
      * Queues the audio data asynchronously for playback (AudioTrack must be in streaming mode).
      * @param audioData the buffer that holds the data to play. This buffer will be returned
      *     to the client via registered callback.
-     * @param bufferIndex the buffer index used to identify audioData. It will be returned to
-     *     the client along with audioData. This helps applications to keep track of audioData.
+     * @param bufferId an integer used to identify audioData. It will be returned to
+     *     the client along with audioData. This helps applications to keep track of audioData,
+     *     e.g., it can be used to store the output buffer index used by the audio codec.
      * @param presentationTimeUs the presentation timestamp in microseconds for the first frame
      *     in the buffer.
      * @throws IllegalStateException if audio track is not set or internal configureation
      *     has not been done correctly.
      */
     public void queueAudio(
-            @NonNull ByteBuffer audioData, int bufferIndex, long presentationTimeUs) {
+            @NonNull ByteBuffer audioData, int bufferId, long presentationTimeUs) {
         if (mAudioTrack == null || mAudioThread == null) {
             throw new IllegalStateException(
                     "AudioTrack is NOT set or audio thread is not created");
         }
 
         synchronized(mAudioLock) {
-            mAudioBuffers.add(new AudioBuffer(audioData, bufferIndex, presentationTimeUs));
+            mAudioBuffers.add(new AudioBuffer(audioData, bufferId, presentationTimeUs));
         }
 
         if (mPlaybackRate != 0.0) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 28fa8fb..c4e3bd6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -189,6 +189,8 @@
      */
     public void stopTracking() {
         if (mRegistered) {
+            mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+            mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_NETWORK_INFO);
             mContext.unregisterReceiver(mReceiver);
             mRegistered = false;
         }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 16c6075..3f0d71c 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -207,4 +207,7 @@
     <!-- Default for Settings.Global.GUEST_USER_ENABLED -->
     <bool name="def_guest_user_enabled">true</bool>
 
+    <!-- Default state of tap to wake -->
+    <bool name="def_double_tap_to_wake">true</bool>
+
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 5f5d61e..ad710a6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1791,7 +1791,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 119;
+            private static final int SETTINGS_VERSION = 120;
 
             private final int mUserId;
 
@@ -1908,6 +1908,17 @@
                     currentVersion = 119;
                 }
 
+                // v120: Add double tap to wake setting.
+                if (currentVersion == 119) {
+                    SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE,
+                            getContext().getResources().getBoolean(
+                                    R.bool.def_double_tap_to_wake) ? "1" : "0",
+                            SettingsState.SYSTEM_PACKAGE_NAME);
+
+                    currentVersion = 120;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 // Return the current version.
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 24f6931..209a233 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -182,6 +182,20 @@
                 android:excludeFromRecents="true">
         </activity>
 
+        <activity android:name=".tuner.TunerActivity"
+                  android:enabled="false"
+                  android:icon="@drawable/icon"
+                  android:theme="@android:style/Theme.Material.Settings"
+                  android:label="@string/system_ui_tuner"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="com.android.settings.action.EXTRA_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                    android:value="com.android.settings.category.device" />
+        </activity>
+
         <!-- Alternate Recents -->
         <activity android:name=".recents.RecentsActivity"
                   android:label="@string/accessibility_desc_recent_apps"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a0b9b65..c74633c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1021,4 +1021,7 @@
     <string name="volume_stream_muted_dnd" translatable="false">%s silent — Total silence</string>
     <string name="volume_stream_limited_dnd" translatable="false">%s — Priority only</string>
     <string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string>
+
+    <!-- Name of special SystemUI debug settings -->
+    <string name="system_ui_tuner">SystemUI Tuner</string>
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
new file mode 100644
index 0000000..263260e
--- /dev/null
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/system_ui_tuner">
+
+        <!-- Tuner prefs go here -->
+
+</PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 3fbc76b..0d331d1 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -225,23 +225,23 @@
         mSubpixelSmoothingRight = context.getResources().getFraction(
                 R.fraction.battery_subpixel_smoothing_right, 1, 1);
 
-        mFramePaint = new Paint();
+        mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mFramePaint.setColor(frameColor);
         mFramePaint.setDither(true);
         mFramePaint.setStrokeWidth(0);
         mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
 
-        mBatteryPaint = new Paint();
+        mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mBatteryPaint.setDither(true);
         mBatteryPaint.setStrokeWidth(0);
         mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
 
-        mTextPaint = new Paint();
+        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
         mTextPaint.setTypeface(font);
         mTextPaint.setTextAlign(Paint.Align.CENTER);
 
-        mWarningTextPaint = new Paint();
+        mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mWarningTextPaint.setColor(mColors[1]);
         font = Typeface.create("sans-serif", Typeface.BOLD);
         mWarningTextPaint.setTypeface(font);
@@ -249,7 +249,7 @@
 
         mChargeColor = context.getColor(R.color.batterymeter_charge_color);
 
-        mBoltPaint = new Paint();
+        mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color));
         mBoltPoints = loadBoltPoints(res);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 5f24619..f4d6f04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -102,7 +102,9 @@
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
         final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
-        state.value = zen != Global.ZEN_MODE_OFF;
+        final boolean newValue = zen != Global.ZEN_MODE_OFF;
+        final boolean valueChanged = state.value != newValue;
+        state.value = newValue;
         state.visible = isVisible(mContext);
         switch (zen) {
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
@@ -133,6 +135,9 @@
         if (mShowingDetail && !state.value) {
             showDetail(false);
         }
+        if (valueChanged) {
+            fireToggleStateChanged(state.value);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 8ccd222..df0a959 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -312,6 +312,9 @@
     // tracking calls to View.setSystemUiVisibility()
     int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
 
+    // last value sent to window manager
+    private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+
     DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
     // XXX: gesture research
@@ -2481,7 +2484,10 @@
 
     private void notifyUiVisibilityChanged(int vis) {
         try {
-            mWindowManagerService.statusBarVisibilityChanged(vis);
+            if (mLastDispatchedSystemUiVisibility != vis) {
+                mWindowManagerService.statusBarVisibilityChanged(vis);
+                mLastDispatchedSystemUiVisibility = vis;
+            }
         } catch (RemoteException ex) {
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
new file mode 100644
index 0000000..c84f618
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.android.systemui.tuner;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class TunerActivity extends Activity {
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getFragmentManager().beginTransaction().replace(android.R.id.content, new TunerFragment())
+                .commit();
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
new file mode 100644
index 0000000..df1b0d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -0,0 +1,44 @@
+/*
+ * 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.android.systemui.tuner;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import android.view.MenuItem;
+
+import com.android.systemui.R;
+
+public class TunerFragment extends PreferenceFragment {
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.tuner_prefs);
+        getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                getActivity().finish();
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+}
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 4f10699..27f2cc8 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -131,7 +131,7 @@
 
     // this should be a monotonically increasing ID
     // used in conjunction with the API version of a device
-    static final long sMinorID = 1;
+    static final long sMinorVersion = 1;
 
     /**
      * Returns an identifier that can be used to identify a particular
@@ -140,8 +140,8 @@
      * @return The minor RenderScript version number
      *
      */
-    public static long getMinorID() {
-        return sMinorID;
+    public static long getMinorVersion() {
+        return sMinorVersion;
     }
 
     /**
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index be8b0fd..d1a12f9 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -400,8 +400,10 @@
     /**
      * Executes a script group
      *
-     * @param inputs inputs to the script group
-     * @return outputs of the script group as an array of objects
+     * @param inputs Values for inputs to the script group, in the order as the
+     *        inputs are added via {@link Builder2#addInput}.
+     * @return Outputs of the script group as an array of objects, in the order
+     *         as futures are passed to {@link Builder2#create}.
      */
 
     public Object[] execute(Object... inputs) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 32b91d2..f5d27f9 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -41,6 +41,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -52,6 +53,7 @@
 import android.util.Log;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 
 import java.util.HashMap;
@@ -1737,17 +1739,32 @@
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
 
-        writer.println("enabled: " + mEnable);
-        writer.println("state: " + mState);
-        writer.println("address: " + mAddress);
-        writer.println("name: " + mName);
+        writer.println("Bluetooth Status");
+        writer.println("  enabled: " + mEnable);
+        writer.println("  state: " + mState);
+        writer.println("  address: " + mAddress);
+        writer.println("  name: " + mName + "\n");
+        writer.flush();
+
         if (mBluetooth == null) {
             writer.println("Bluetooth Service not connected");
         } else {
+            ParcelFileDescriptor pfd = null;
             try {
-                writer.println(mBluetooth.dump());
+                pfd = ParcelFileDescriptor.dup(fd);
+                mBluetooth.dump(pfd);
             } catch (RemoteException re) {
                 writer.println("RemoteException while calling Bluetooth Service");
+            } catch (IOException ioe) {
+                writer.println("IOException attempting to dup() fd");
+            } finally {
+                if (pfd != null) {
+                    try {
+                        pfd.close();
+                    } catch (IOException ioe) {
+                        writer.println("IOException attempting to close() fd");
+                    }
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d035c92..f4671a9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15994,6 +15994,11 @@
         // By default broadcasts do not go to stopped apps.
         intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
 
+        // If we have not finished booting, don't allow this to launch new processes.
+        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        }
+
         if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                 (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
                 + " ordered=" + ordered + " userid=" + userId);
@@ -16455,8 +16460,7 @@
             // if the caller really truly claims to know what they're doing, go
             // ahead and allow the broadcast without launching any receivers
             if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
-                intent = new Intent(intent);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                // This will be turned into a FLAG_RECEIVER_REGISTERED_ONLY later on if needed.
             } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
                         + " before boot completion");
@@ -16906,6 +16910,9 @@
                 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
                     intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
                     intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    if (!mProcessesReady) {
+                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    }
                     broadcastIntentLocked(null, null, intent,
                             null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                             false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a86df2d..6574538 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -748,6 +748,14 @@
             return true;
         }
 
+        if (hasVisibleBehindActivity()) {
+            // Stop visible behind activity before going to sleep.
+            final ActivityRecord r = mActivityContainer.mActivityDisplay.mVisibleBehindActivity;
+            mStackSupervisor.mStoppingActivities.add(r);
+            if (DEBUG_STATES) Slog.v(TAG, "Sleep still waiting to stop visible behind " + r);
+            return true;
+        }
+
         return false;
     }
 
@@ -1007,7 +1015,7 @@
                     // the current instance before starting the new one.
                     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev);
                     destroyActivityLocked(prev, true, "pause-config");
-                } else if (!hasVisibleBehindActivity()) {
+                } else if (!hasVisibleBehindActivity() || mService.isSleepingOrShuttingDown()) {
                     // If we were visible then resumeTopActivities will release resources before
                     // stopping.
                     mStackSupervisor.mStoppingActivities.add(prev);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f3b4516..5e9f2b0 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -22,6 +22,7 @@
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
@@ -90,6 +91,7 @@
     private static final String ATTR_CALLING_UID = "calling_uid";
     private static final String ATTR_CALLING_PACKAGE = "calling_package";
     private static final String ATTR_RESIZEABLE = "resizeable";
+    private static final String ATTR_PRIVILEGED = "privileged";
 
     private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
 
@@ -127,6 +129,9 @@
                             // the root activity.
     int mLockTaskMode;      // Which tasklock mode to launch this task in. One of
                             // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
+    private boolean mPrivileged;    // The root activity application of this task holds
+                                    // privileged permissions.
+
     /** Can't be put in lockTask mode. */
     final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
     /** Can enter lockTask with user approval if not already in lockTask. */
@@ -245,7 +250,7 @@
             long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
             boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
             int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
-            int callingUid, String callingPackage, boolean resizeable) {
+            int callingUid, String callingPackage, boolean resizeable, boolean privileged) {
         mService = service;
         mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
                 TaskPersister.IMAGE_EXTENSION;
@@ -281,6 +286,7 @@
         mCallingUid = callingUid;
         mCallingPackage = callingPackage;
         mResizeable = resizeable;
+        mPrivileged = privileged;
     }
 
     void touchActiveTime() {
@@ -381,6 +387,7 @@
         }
         mResizeable = info.resizeable;
         mLockTaskMode = info.lockTaskLaunchMode;
+        mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
         setLockTaskAuth();
     }
 
@@ -734,14 +741,6 @@
         performClearTaskAtIndexLocked(0);
     }
 
-    private boolean isPrivileged() {
-        final ProcessRecord proc = mService.mProcessNames.get(mCallingPackage, mCallingUid);
-        if (proc != null) {
-                return (proc.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
-        }
-        return false;
-    }
-
     void setLockTaskAuth() {
         switch (mLockTaskMode) {
             case LOCK_TASK_LAUNCH_MODE_DEFAULT:
@@ -750,12 +749,12 @@
                 break;
 
             case LOCK_TASK_LAUNCH_MODE_NEVER:
-                mLockTaskAuth = isPrivileged() ?
+                mLockTaskAuth = mPrivileged ?
                         LOCK_TASK_AUTH_DONT_LOCK : LOCK_TASK_AUTH_PINNABLE;
                 break;
 
             case LOCK_TASK_LAUNCH_MODE_ALWAYS:
-                mLockTaskAuth = isPrivileged() ?
+                mLockTaskAuth = mPrivileged ?
                         LOCK_TASK_AUTH_LAUNCHABLE: LOCK_TASK_AUTH_PINNABLE;
                 break;
 
@@ -930,6 +929,7 @@
         out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
         out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
         out.attribute(null, ATTR_RESIZEABLE, String.valueOf(mResizeable));
+        out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
 
         if (affinityIntent != null) {
             out.startTag(null, TAG_AFFINITYINTENT);
@@ -993,6 +993,7 @@
         int callingUid = -1;
         String callingPackage = "";
         boolean resizeable = false;
+        boolean privileged = false;
 
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
@@ -1048,6 +1049,8 @@
                 callingPackage = attrValue;
             } else if (ATTR_RESIZEABLE.equals(attrName)) {
                 resizeable = Boolean.valueOf(attrValue);
+            } else if (ATTR_PRIVILEGED.equals(attrName)) {
+                privileged = Boolean.valueOf(attrValue);
             } else {
                 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
             }
@@ -1107,7 +1110,7 @@
                 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
                 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                 taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
-                callingUid, callingPackage, resizeable);
+                callingUid, callingPackage, resizeable, privileged);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
             activities.get(activityNdx).task = task;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 2149b7a..47ddfec 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -43,7 +43,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -1106,7 +1105,8 @@
             }
             // Check if the ringer mode handles this adjustment. If it does we don't
             // need to adjust the volume further.
-            final int result = checkForRingerModeChange(aliasIndex, direction, step, streamState.mIsMuted);
+            final int result = checkForRingerModeChange(aliasIndex, direction, step,
+                    streamState.mIsMuted);
             adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
             // If suppressing a volume adjustment in silent mode, display the UI hint
             if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -1117,6 +1117,11 @@
                 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
             }
         }
+        // If the ringermode is suppressing media, prevent changes
+        if (streamTypeAlias == AudioSystem.STREAM_MUSIC
+                && (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) {
+            adjustVolume = false;
+        }
 
         int oldIndex = mStreamStates[streamType].getIndex(device);
 
@@ -1796,20 +1801,14 @@
         broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
     }
 
-    private void setRingerModeInt(int ringerMode, boolean persist) {
-        final boolean change;
-        synchronized(mSettingsLock) {
-            change = mRingerMode != ringerMode;
-            mRingerMode = ringerMode;
-        }
-
+    private void muteRingerModeStreams() {
         // Mute stream if not previously muted by ringer mode and ringer mode
         // is not RINGER_MODE_NORMAL and stream is affected by ringer mode.
         // Unmute stream if previously muted by ringer mode and ringer mode
         // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
         int numStreamTypes = AudioSystem.getNumStreamTypes();
-        final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
-                || ringerMode == AudioManager.RINGER_MODE_SILENT;
+        final boolean ringerModeMute = mRingerMode == AudioManager.RINGER_MODE_VIBRATE
+                || mRingerMode == AudioManager.RINGER_MODE_SILENT;
         for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
             final boolean isMuted = isStreamMutedByRingerMode(streamType);
             final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType);
@@ -1846,6 +1845,16 @@
                 mRingerModeMutedStreams |= (1 << streamType);
             }
         }
+    }
+
+    private void setRingerModeInt(int ringerMode, boolean persist) {
+        final boolean change;
+        synchronized(mSettingsLock) {
+            change = mRingerMode != ringerMode;
+            mRingerMode = ringerMode;
+        }
+
+        muteRingerModeStreams();
 
         // Post a persist ringer mode msg
         if (persist) {
@@ -3084,30 +3093,19 @@
         return (mRingerModeMutedStreams & (1 << streamType)) != 0;
     }
 
-    boolean updateRingerModeAffectedStreams() {
-        int ringerModeAffectedStreams;
-        // make sure settings for ringer mode are consistent with device type: non voice capable
-        // devices (tablets) include media stream in silent mode whereas phones don't.
-        ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
+    private boolean updateRingerModeAffectedStreams() {
+        int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
                 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
                  (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
                  UserHandle.USER_CURRENT);
 
-        // ringtone, notification and system streams are always affected by ringer mode
-        ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)|
-                                        (1 << AudioSystem.STREAM_NOTIFICATION)|
-                                        (1 << AudioSystem.STREAM_SYSTEM);
-
-        switch (mPlatformType) {
-            case AudioSystem.PLATFORM_TELEVISION:
-                ringerModeAffectedStreams = 0;
-                break;
-            default:
-                ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
-                break;
+        if (mPlatformType == AudioSystem.PLATFORM_TELEVISION) {
+            ringerModeAffectedStreams = 0;
+        } else if (mRingerModeDelegate != null) {
+            ringerModeAffectedStreams = mRingerModeDelegate
+                    .getRingerModeAffectedStreams(ringerModeAffectedStreams);
         }
-
         synchronized (mCameraSoundForced) {
             if (mCameraSoundForced) {
                 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
@@ -5541,13 +5539,35 @@
         pw.println("\nRinger mode: ");
         pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
         pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
-        pw.print("- ringer mode affected streams = 0x");
-        pw.println(Integer.toHexString(mRingerModeAffectedStreams));
-        pw.print("- ringer mode muted streams = 0x");
-        pw.println(Integer.toHexString(mRingerModeMutedStreams));
+        dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
+        dumpRingerModeStreams(pw, "muted", mRingerModeMutedStreams);
         pw.print("- delegate = "); pw.println(mRingerModeDelegate);
     }
 
+    private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
+        pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
+        pw.print(Integer.toHexString(streams));
+        if (streams != 0) {
+            pw.print(" (");
+            boolean first = true;
+            for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
+                final int stream = (1 << i);
+                if ((streams & stream) != 0) {
+                    if (!first) pw.print(',');
+                    pw.print(AudioSystem.STREAM_NAMES[i]);
+                    streams &= ~stream;
+                    first = false;
+                }
+            }
+            if (streams != 0) {
+                if (!first) pw.print(',');
+                pw.print(streams);
+            }
+            pw.print(')');
+        }
+        pw.println();
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -5780,6 +5800,7 @@
         public void setRingerModeDelegate(RingerModeDelegate delegate) {
             mRingerModeDelegate = delegate;
             if (mRingerModeDelegate != null) {
+                updateRingerModeAffectedStreams();
                 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
             }
         }
@@ -5820,6 +5841,15 @@
         public int getVolumeControllerUid() {
             return mControllerService.mUid;
         }
+
+        @Override
+        public void updateRingerModeAffectedStreamsInternal() {
+            synchronized (mSettingsLock) {
+                if (updateRingerModeAffectedStreams()) {
+                    setRingerModeInt(getRingerModeInternal(), false);
+                }
+            }
+        }
     }
 
     //==========================================================================================
diff --git a/services/core/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java
index b411a0d..6ba25a5 100644
--- a/services/core/java/com/android/server/display/DisplayAdapter.java
+++ b/services/core/java/com/android/server/display/DisplayAdapter.java
@@ -18,8 +18,10 @@
 
 import android.content.Context;
 import android.os.Handler;
+import android.view.Display;
 
 import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * A display adapter makes zero or more display devices available to the system
@@ -42,6 +44,11 @@
     public static final int DISPLAY_DEVICE_EVENT_CHANGED = 2;
     public static final int DISPLAY_DEVICE_EVENT_REMOVED = 3;
 
+    /**
+     * Used to generate globally unique display mode ids.
+     */
+    private static final AtomicInteger NEXT_DISPLAY_MODE_ID = new AtomicInteger(1);  // 0 = no mode.
+
     // Called with SyncRoot lock held.
     public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener, String name) {
@@ -122,6 +129,11 @@
         });
     }
 
+    public static Display.Mode createMode(int width, int height, float refreshRate) {
+        return new Display.Mode(
+                NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate);
+    }
+
     public interface Listener {
         public void onDisplayDeviceEvent(DisplayDevice device, int event);
         public void onTraversalRequested();
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index ee36972..93bda46 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayViewport;
 import android.os.IBinder;
+import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
@@ -132,9 +133,9 @@
     }
 
     /**
-     * Sets the refresh rate, if supported.
+     * Sets the mode, if supported.
      */
-    public void requestRefreshRateLocked(float refreshRate) {
+    public void requestModeInTransactionLocked(int id) {
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index ebf6e4e..0db3e3f 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -23,7 +23,6 @@
 
 import java.util.Arrays;
 
-import libcore.util.EmptyArray;
 import libcore.util.Objects;
 
 /**
@@ -137,14 +136,19 @@
     public int height;
 
     /**
-     * The refresh rate of the display, in frames per second.
+     * The active mode of the display.
      */
-    public float refreshRate;
+    public int modeId;
 
     /**
-     * The supported refresh rates of the display at the current resolution in frames per second.
+     * The default mode of the display.
      */
-    public float[] supportedRefreshRates = EmptyArray.FLOAT;
+    public int defaultModeId;
+
+    /**
+     * The supported modes of the display.
+     */
+    public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
 
     /**
      * The nominal apparent density of the display in DPI used for layout calculations.
@@ -264,8 +268,9 @@
                 || !Objects.equal(uniqueId, other.uniqueId)
                 || width != other.width
                 || height != other.height
-                || refreshRate != other.refreshRate
-                || !Arrays.equals(supportedRefreshRates, other.supportedRefreshRates)
+                || modeId != other.modeId
+                || defaultModeId != other.defaultModeId
+                || !Arrays.equals(supportedModes, other.supportedModes)
                 || densityDpi != other.densityDpi
                 || xDpi != other.xDpi
                 || yDpi != other.yDpi
@@ -293,8 +298,9 @@
         uniqueId = other.uniqueId;
         width = other.width;
         height = other.height;
-        refreshRate = other.refreshRate;
-        supportedRefreshRates = other.supportedRefreshRates;
+        modeId = other.modeId;
+        defaultModeId = other.defaultModeId;
+        supportedModes = other.supportedModes;
         densityDpi = other.densityDpi;
         xDpi = other.xDpi;
         yDpi = other.yDpi;
@@ -317,8 +323,9 @@
         sb.append("DisplayDeviceInfo{\"");
         sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", ");
         sb.append(width).append(" x ").append(height);
-        sb.append(", ").append(refreshRate).append(" fps");
-        sb.append(", supportedRefreshRates ").append(Arrays.toString(supportedRefreshRates));
+        sb.append(", modeId ").append(modeId);
+        sb.append(", defaultModeId ").append(defaultModeId);
+        sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
         sb.append(", density ").append(densityDpi);
         sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
         sb.append(", appVsyncOff ").append(appVsyncOffsetNanos);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 1e87433..7440b8c 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -842,7 +842,7 @@
     }
 
     private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
-            float requestedRefreshRate, boolean inTraversal) {
+            float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
         synchronized (mSyncRoot) {
             LogicalDisplay display = mLogicalDisplays.get(displayId);
             if (display == null) {
@@ -857,12 +857,17 @@
                 display.setHasContentLocked(hasContent);
                 scheduleTraversalLocked(inTraversal);
             }
-            if (display.getRequestedRefreshRateLocked() != requestedRefreshRate) {
+            if (requestedModeId == 0 && requestedRefreshRate != 0) {
+                // Scan supported modes returned by display.getInfo() to find a mode with the same
+                // size as the default display mode but with the specified refresh rate instead.
+                requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
+                        requestedRefreshRate);
+            }
+            if (display.getRequestedModeIdLocked() != requestedModeId) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Display " + displayId + " has requested a new refresh rate: "
-                            + requestedRefreshRate + "fps");
+                    Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
                 }
-                display.setRequestedRefreshRateLocked(requestedRefreshRate);
+                display.setRequestedModeIdLocked(requestedModeId);
                 scheduleTraversalLocked(inTraversal);
             }
         }
@@ -1564,8 +1569,9 @@
 
         @Override
         public void setDisplayProperties(int displayId, boolean hasContent,
-                float requestedRefreshRate, boolean inTraversal) {
-            setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, inTraversal);
+                float requestedRefreshRate, int requestedMode, boolean inTraversal) {
+            setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
+                    requestedMode, inTraversal);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index e87f265..cc7d848 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -35,7 +35,7 @@
 import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
-import java.util.Arrays;
+import java.util.ArrayList;
 
 /**
  * A display adapter for the local displays managed by Surface Flinger.
@@ -56,6 +56,7 @@
 
     private final SparseArray<LocalDisplayDevice> mDevices =
             new SparseArray<LocalDisplayDevice>();
+    @SuppressWarnings("unused")  // Becomes active at instantiation time.
     private HotplugDisplayEventReceiver mHotplugReceiver;
 
     // Called with SyncRoot lock held.
@@ -136,28 +137,22 @@
 
     private final class LocalDisplayDevice extends DisplayDevice {
         private final int mBuiltInDisplayId;
-        private final SurfaceControl.PhysicalDisplayInfo mPhys;
-        private final int mDefaultPhysicalDisplayInfo;
         private final Light mBacklight;
+        private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
         private int mState = Display.STATE_UNKNOWN;
         private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
-        private float[] mSupportedRefreshRates;
-        private int[] mRefreshRateConfigIndices;
-        private float mLastRequestedRefreshRate;
-
+        private int mDefaultModeId;
+        private int mActiveModeId;
+        private boolean mActiveModeInvalid;
 
         public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
                 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
             super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
             mBuiltInDisplayId = builtInDisplayId;
-            mPhys = new SurfaceControl.PhysicalDisplayInfo(
-                    physicalDisplayInfos[activeDisplayInfo]);
-            mDefaultPhysicalDisplayInfo = activeDisplayInfo;
-            updateSupportedRefreshRatesLocked(physicalDisplayInfos, mPhys);
-
+            updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo);
             if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                 LightsManager lights = LocalServices.getService(LightsManager.class);
                 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
@@ -168,14 +163,73 @@
 
         public boolean updatePhysicalDisplayInfoLocked(
                 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
-            SurfaceControl.PhysicalDisplayInfo newPhys = physicalDisplayInfos[activeDisplayInfo];
-            if (!mPhys.equals(newPhys)) {
-                mPhys.copyFrom(newPhys);
-                updateSupportedRefreshRatesLocked(physicalDisplayInfos, mPhys);
-                mHavePendingChanges = true;
-                return true;
+            // Build an updated list of all existing modes.
+            boolean modesAdded = false;
+            DisplayModeRecord activeRecord = null;
+            ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
+            for (int i = 0; i < physicalDisplayInfos.length; i++) {
+                SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
+                DisplayModeRecord record = findDisplayModeRecord(info);
+                if (record != null) {
+                    record.mPhysIndex = i;
+                } else {
+                    record = new DisplayModeRecord(info, i);
+                    modesAdded = true;
+                }
+                records.add(record);
+                if (i == activeDisplayInfo) {
+                    activeRecord = record;
+                }
             }
-            return false;
+            // Check whether surface flinger spontaneously changed modes out from under us. Schedule
+            // traversals to ensure that the correct state is reapplied if necessary.
+            if (mActiveModeId != 0
+                    && mActiveModeId != activeRecord.mMode.getModeId()) {
+                mActiveModeInvalid = true;
+                sendTraversalRequestLocked();
+            }
+            // If no modes were added and we have the same number of modes as before, then nothing
+            // actually changed except possibly the physical index (which we only care about when
+            // setting the mode) so we're done.
+            if (records.size() == mSupportedModes.size() && !modesAdded) {
+                return false;
+            }
+            // Update the index of modes.
+            mHavePendingChanges = true;
+            mSupportedModes.clear();
+            for (DisplayModeRecord record : records) {
+                mSupportedModes.put(record.mMode.getModeId(), record);
+            }
+            // Update the default mode if needed.
+            if (mSupportedModes.indexOfKey(mDefaultModeId) < 0) {
+                if (mDefaultModeId != 0) {
+                    Slog.w(TAG, "Default display mode no longer available, using currently active"
+                            + " mode as default.");
+                }
+                mDefaultModeId = activeRecord.mMode.getModeId();
+            }
+            // Determine whether the active mode is still there.
+            if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
+                if (mActiveModeId != 0) {
+                    Slog.w(TAG, "Active display mode no longer available, reverting to default"
+                            + " mode.");
+                }
+                mActiveModeId = mDefaultModeId;
+                mActiveModeInvalid = true;
+            }
+            // Schedule traversals so that we apply pending changes.
+            sendTraversalRequestLocked();
+            return true;
+        }
+
+        private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
+            for (int i = 0; i < mSupportedModes.size(); i++) {
+                DisplayModeRecord record = mSupportedModes.valueAt(i);
+                if (record.mPhys.equals(info)) {
+                    return record;
+                }
+            }
+            return null;
         }
 
         @Override
@@ -189,19 +243,25 @@
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
+                SurfaceControl.PhysicalDisplayInfo phys = mSupportedModes.get(mActiveModeId).mPhys;
                 mInfo = new DisplayDeviceInfo();
-                mInfo.width = mPhys.width;
-                mInfo.height = mPhys.height;
-                mInfo.refreshRate = mPhys.refreshRate;
-                mInfo.supportedRefreshRates = mSupportedRefreshRates;
-                mInfo.appVsyncOffsetNanos = mPhys.appVsyncOffsetNanos;
-                mInfo.presentationDeadlineNanos = mPhys.presentationDeadlineNanos;
+                mInfo.width = phys.width;
+                mInfo.height = phys.height;
+                mInfo.modeId = mActiveModeId;
+                mInfo.defaultModeId = mDefaultModeId;
+                mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
+                for (int i = 0; i < mSupportedModes.size(); i++) {
+                    DisplayModeRecord record = mSupportedModes.valueAt(i);
+                    mInfo.supportedModes[i] = record.mMode;
+                }
+                mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
+                mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
                 mInfo.state = mState;
                 mInfo.uniqueId = getUniqueId();
 
                 // Assume that all built-in displays that have secure output (eg. HDCP) also
                 // support compositing from gralloc protected buffers.
-                if (mPhys.secure) {
+                if (phys.secure) {
                     mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
                             | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
                 }
@@ -212,9 +272,9 @@
                     mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
                             | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
                     mInfo.type = Display.TYPE_BUILT_IN;
-                    mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
-                    mInfo.xDpi = mPhys.xDpi;
-                    mInfo.yDpi = mPhys.yDpi;
+                    mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
+                    mInfo.xDpi = phys.xDpi;
+                    mInfo.yDpi = phys.yDpi;
                     mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
                 } else {
                     mInfo.type = Display.TYPE_HDMI;
@@ -222,7 +282,7 @@
                     mInfo.name = getContext().getResources().getString(
                             com.android.internal.R.string.display_manager_hdmi_display_name);
                     mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
-                    mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
+                    mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);
 
                     // For demonstration purposes, allow rotation of the external display.
                     // In the future we might allow the user to configure this directly.
@@ -332,30 +392,29 @@
         }
 
         @Override
-        public void requestRefreshRateLocked(float refreshRate) {
-            if (mLastRequestedRefreshRate == refreshRate) {
+        public void requestModeInTransactionLocked(int modeId) {
+            if (modeId == 0) {
+                modeId = mDefaultModeId;
+            } else if (mSupportedModes.indexOfKey(modeId) < 0) {
+                Slog.w(TAG, "Requested mode " + modeId + " is not supported by this display,"
+                        + " reverting to default display mode.");
+                modeId = mDefaultModeId;
+            }
+            if (mActiveModeId == modeId && !mActiveModeInvalid) {
                 return;
             }
-            mLastRequestedRefreshRate = refreshRate;
-            if (refreshRate != 0) {
-                final int N = mSupportedRefreshRates.length;
-                for (int i = 0; i < N; i++) {
-                    if (refreshRate == mSupportedRefreshRates[i]) {
-                        final int configIndex = mRefreshRateConfigIndices[i];
-                        SurfaceControl.setActiveConfig(getDisplayTokenLocked(), configIndex);
-                        return;
-                    }
-                }
-                Slog.w(TAG, "Requested refresh rate " + refreshRate + " is unsupported.");
-            }
-            SurfaceControl.setActiveConfig(getDisplayTokenLocked(), mDefaultPhysicalDisplayInfo);
+            DisplayModeRecord record = mSupportedModes.get(modeId);
+            SurfaceControl.setActiveConfig(getDisplayTokenLocked(), record.mPhysIndex);
+            mActiveModeId = modeId;
+            mActiveModeInvalid = false;
+            updateDeviceInfoLocked();
         }
 
         @Override
         public void dumpLocked(PrintWriter pw) {
             super.dumpLocked(pw);
             pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
-            pw.println("mPhys=" + mPhys);
+            pw.println("mActiveModeId=" + mActiveModeId);
             pw.println("mState=" + Display.stateToString(mState));
             pw.println("mBrightness=" + mBrightness);
             pw.println("mBacklight=" + mBacklight);
@@ -365,29 +424,20 @@
             mInfo = null;
             sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
         }
+    }
 
-        private void updateSupportedRefreshRatesLocked(
-                SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos,
-                SurfaceControl.PhysicalDisplayInfo activePhys) {
-            final int N = physicalDisplayInfos.length;
-            int idx = 0;
-            mSupportedRefreshRates = new float[N];
-            mRefreshRateConfigIndices = new int[N];
-            for (int i = 0; i < N; i++) {
-                final SurfaceControl.PhysicalDisplayInfo phys = physicalDisplayInfos[i];
-                if (activePhys.width == phys.width
-                        && activePhys.height == phys.height
-                        && activePhys.density == phys.density
-                        && activePhys.xDpi == phys.xDpi
-                        && activePhys.yDpi == phys.yDpi) {
-                    mSupportedRefreshRates[idx] = phys.refreshRate;
-                    mRefreshRateConfigIndices[idx++] = i;
-                }
-            }
-            if (idx != N) {
-                mSupportedRefreshRates = Arrays.copyOfRange(mSupportedRefreshRates, 0, idx);
-                mRefreshRateConfigIndices = Arrays.copyOfRange(mRefreshRateConfigIndices, 0, idx);
-            }
+    /**
+     * Keeps track of a display configuration.
+     */
+    private static final class DisplayModeRecord {
+        public final Display.Mode mMode;
+        public final SurfaceControl.PhysicalDisplayInfo mPhys;
+        public int mPhysIndex;
+
+        public DisplayModeRecord(SurfaceControl.PhysicalDisplayInfo phys, int physIndex) {
+            mMode = createMode(phys.width, phys.height, phys.refreshRate);
+            mPhys = phys;
+            mPhysIndex = physIndex;
         }
     }
 
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 65dc72f..7accbf2 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -73,8 +73,7 @@
     // True if the logical display has unique content.
     private boolean mHasContent;
 
-    // The pending requested refresh rate. 0 if no request is pending.
-    private float mRequestedRefreshRate;
+    private int mRequestedModeId;
 
     // The display offsets to apply to the display projection.
     private int mDisplayOffsetX;
@@ -219,9 +218,10 @@
             mBaseDisplayInfo.logicalWidth = deviceInfo.width;
             mBaseDisplayInfo.logicalHeight = deviceInfo.height;
             mBaseDisplayInfo.rotation = Surface.ROTATION_0;
-            mBaseDisplayInfo.refreshRate = deviceInfo.refreshRate;
-            mBaseDisplayInfo.supportedRefreshRates = Arrays.copyOf(
-                    deviceInfo.supportedRefreshRates, deviceInfo.supportedRefreshRates.length);
+            mBaseDisplayInfo.modeId = deviceInfo.modeId;
+            mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
+            mBaseDisplayInfo.supportedModes = Arrays.copyOf(
+                    deviceInfo.supportedModes, deviceInfo.supportedModes.length);
             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
             mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
             mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
@@ -259,14 +259,19 @@
      */
     public void configureDisplayInTransactionLocked(DisplayDevice device,
             boolean isBlanked) {
-        final DisplayInfo displayInfo = getDisplayInfoLocked();
-        final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
-
         // Set the layer stack.
         device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
 
-        // Set the refresh rate
-        device.requestRefreshRateLocked(mRequestedRefreshRate);
+        // Set the mode.
+        if (device == mPrimaryDisplayDevice) {
+            device.requestModeInTransactionLocked(mRequestedModeId);
+        } else {
+            device.requestModeInTransactionLocked(0);  // Revert to default.
+        }
+
+        // Only grab the display info now as it may have been changed based on the requests above.
+        final DisplayInfo displayInfo = getDisplayInfoLocked();
+        final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
 
         // Set the viewport.
         // This is the area of the logical display that we intend to show on the
@@ -351,20 +356,17 @@
     }
 
     /**
-     * Requests the given refresh rate.
-     * @param requestedRefreshRate The desired refresh rate.
+     * Requests the given mode.
      */
-    public void setRequestedRefreshRateLocked(float requestedRefreshRate) {
-        mRequestedRefreshRate = requestedRefreshRate;
+    public void setRequestedModeIdLocked(int modeId) {
+        mRequestedModeId = modeId;
     }
 
     /**
-     * Gets the pending requested refresh rate.
-     *
-     * @return The pending refresh rate requested
+     * Returns the pending requested mode.
      */
-    public float getRequestedRefreshRateLocked() {
-        return mRequestedRefreshRate;
+    public int getRequestedModeIdLocked() {
+        return mRequestedModeId;
     }
 
     /**
@@ -393,7 +395,7 @@
         pw.println("mDisplayId=" + mDisplayId);
         pw.println("mLayerStack=" + mLayerStack);
         pw.println("mHasContent=" + mHasContent);
-        pw.println("mRequestedRefreshRate=" + mRequestedRefreshRate);
+        pw.println("mRequestedMode=" + mRequestedModeId);
         pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
         pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
                 mPrimaryDisplayDevice.getNameLocked() : "null"));
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index af9f456..080665aa 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -197,6 +197,7 @@
         private final long mDisplayPresentationDeadlineNanos;
         private final int mDensityDpi;
         private final boolean mSecure;
+        private final Display.Mode mMode;
 
         private int mState;
         private SurfaceTexture mSurfaceTexture;
@@ -217,6 +218,7 @@
             mSecure = secure;
             mState = state;
             mSurfaceTexture = surfaceTexture;
+            mMode = createMode(width, height, refreshRate);
         }
 
         public void destroyLocked() {
@@ -251,8 +253,9 @@
                 mInfo.uniqueId = getUniqueId();
                 mInfo.width = mWidth;
                 mInfo.height = mHeight;
-                mInfo.refreshRate = mRefreshRate;
-                mInfo.supportedRefreshRates = new float[] { mRefreshRate };
+                mInfo.modeId = mMode.getModeId();
+                mInfo.defaultModeId = mMode.getModeId();
+                mInfo.supportedModes = new Display.Mode[] { mMode };
                 mInfo.densityDpi = mDensityDpi;
                 mInfo.xDpi = mDensityDpi;
                 mInfo.yDpi = mDensityDpi;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index 3f4eab9..786889a 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -302,7 +302,8 @@
         @Override
         public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                 int width, int height) {
-            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate,
+            mListener.onWindowCreated(surfaceTexture,
+                    mDefaultDisplayInfo.getMode().getRefreshRate(),
                     mDefaultDisplayInfo.presentationDeadlineNanos, mDefaultDisplayInfo.state);
         }
 
@@ -377,4 +378,4 @@
         public void onWindowDestroyed();
         public void onStateChanged(int state);
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 7f961ae..986efd69 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -165,6 +165,8 @@
         private static final int PENDING_SURFACE_CHANGE = 0x01;
         private static final int PENDING_RESIZE = 0x02;
 
+        private static final float REFRESH_RATE = 60.0f;
+
         private final IBinder mAppToken;
         private final int mOwnerUid;
         final String mOwnerPackageName;
@@ -181,6 +183,7 @@
         private boolean mStopped;
         private int mPendingChanges;
         private int mUniqueIndex;
+        private Display.Mode mMode;
 
         public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
                 int ownerUid, String ownerPackageName,
@@ -193,6 +196,7 @@
             mName = name;
             mWidth = width;
             mHeight = height;
+            mMode = createMode(width, height, REFRESH_RATE);
             mDensityDpi = densityDpi;
             mSurface = surface;
             mFlags = flags;
@@ -262,6 +266,7 @@
                 sendTraversalRequestLocked();
                 mWidth = width;
                 mHeight = height;
+                mMode = createMode(width, height, REFRESH_RATE);
                 mDensityDpi = densityDpi;
                 mInfo = null;
                 mPendingChanges |= PENDING_RESIZE;
@@ -290,12 +295,13 @@
                 mInfo.uniqueId = getUniqueId();
                 mInfo.width = mWidth;
                 mInfo.height = mHeight;
-                mInfo.refreshRate = 60;
-                mInfo.supportedRefreshRates = new float[] { 60.0f };
+                mInfo.modeId = mMode.getModeId();
+                mInfo.defaultModeId = mMode.getModeId();
+                mInfo.supportedModes = new Display.Mode[] { mMode };
                 mInfo.densityDpi = mDensityDpi;
                 mInfo.xDpi = mDensityDpi;
                 mInfo.yDpi = mDensityDpi;
-                mInfo.presentationDeadlineNanos = 1000000000L / (int) mInfo.refreshRate; // 1 frame
+                mInfo.presentationDeadlineNanos = 1000000000L / (int) REFRESH_RATE; // 1 frame
                 mInfo.flags = 0;
                 if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index f163555..64bc729 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -583,6 +583,7 @@
         private final float mRefreshRate;
         private final int mFlags;
         private final String mAddress;
+        private final Display.Mode mMode;
 
         private Surface mSurface;
         private DisplayDeviceInfo mInfo;
@@ -598,6 +599,7 @@
             mFlags = flags;
             mAddress = address;
             mSurface = surface;
+            mMode = createMode(width, height, refreshRate);
         }
 
         public void destroyLocked() {
@@ -628,8 +630,9 @@
                 mInfo.uniqueId = getUniqueId();
                 mInfo.width = mWidth;
                 mInfo.height = mHeight;
-                mInfo.refreshRate = mRefreshRate;
-                mInfo.supportedRefreshRates = new float[] { mRefreshRate };
+                mInfo.modeId = mMode.getModeId();
+                mInfo.defaultModeId = mMode.getModeId();
+                mInfo.supportedModes = new Display.Mode[] { mMode };
                 mInfo.presentationDeadlineNanos = 1000000000L / (int) mRefreshRate; // 1 frame
                 mInfo.flags = mFlags;
                 mInfo.type = Display.TYPE_WIFI;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 8031c05..77b800e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -737,6 +737,9 @@
         }
     }
 
+    void setAutoDeviceOff(boolean enabled) {
+    }
+
     /**
      * Called when a hot-plug event issued.
      *
@@ -829,8 +832,11 @@
      *
      * @param initiatedByCec true if this power sequence is initiated
      *        by the reception the CEC messages like &lt;Standby&gt;
+     * @param standbyAction Intent action that drives the standby process,
+     *        either {@link HdmiControlService#STANDBY_SCREEN_OFF} or
+     *        {@link HdmiControlService#STANDBY_SHUTDOWN}
      */
-    protected void onStandby(boolean initiatedByCec) {}
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {}
 
     /**
      * Disable device. {@code callback} is used to get notified when all pending
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index fd3364a..30a9b43 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -23,6 +23,7 @@
 import android.os.PowerManager.WakeLock;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.provider.Settings.Global;
 import android.util.Slog;
 
 import com.android.internal.util.IndentingPrintWriter;
@@ -47,8 +48,17 @@
     // Lazily initialized - should call getWakeLock() to get the instance.
     private ActiveWakeLock mWakeLock;
 
+    // If true, turn off TV upon standby. False by default.
+    private boolean mAutoTvOff;
+
     HdmiCecLocalDevicePlayback(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
+
+        mAutoTvOff = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, false);
+
+        // The option is false by default. Update settings db as well to have the right
+        // initial setting on UI.
+        mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, mAutoTvOff);
     }
 
     @Override
@@ -141,6 +151,35 @@
         }
     }
 
+    @Override
+    @ServiceThreadOnly
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {
+        assertRunOnServiceThread();
+        if (!mService.isControlEnabled() || initiatedByCec) {
+            return;
+        }
+        switch (standbyAction) {
+            case HdmiControlService.STANDBY_SCREEN_OFF:
+                if (mAutoTvOff) {
+                    mService.sendCecCommand(
+                            HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
+                }
+                break;
+            case HdmiControlService.STANDBY_SHUTDOWN:
+                // ACTION_SHUTDOWN is taken as a signal to power off all the devices.
+                mService.sendCecCommand(
+                        HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_BROADCAST));
+                break;
+        }
+    }
+
+    @Override
+    @ServiceThreadOnly
+    void setAutoDeviceOff(boolean enabled) {
+        assertRunOnServiceThread();
+        mAutoTvOff = enabled;
+    }
+
     @ServiceThreadOnly
     void setActiveSource(boolean on) {
         assertRunOnServiceThread();
@@ -295,6 +334,7 @@
     protected void dump(final IndentingPrintWriter pw) {
         super.dump(pw);
         pw.println("mIsActiveSource: " + mIsActiveSource);
+        pw.println("mAutoTvOff:" + mAutoTvOff);
     }
 
     // Wrapper interface over PowerManager.WakeLock
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 51ba32d..96cb51c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1583,6 +1583,7 @@
         }
     }
 
+    @Override
     @ServiceThreadOnly
     void setAutoDeviceOff(boolean enabled) {
         assertRunOnServiceThread();
@@ -1659,7 +1660,7 @@
 
     @Override
     @ServiceThreadOnly
-    protected void onStandby(boolean initiatedByCec) {
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {
         assertRunOnServiceThread();
         // Seq #11
         if (!mService.isControlEnabled()) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 2cbc1b9..66f7861 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -106,6 +106,12 @@
     static final int INITIATED_BY_WAKE_UP_MESSAGE = 3;
     static final int INITIATED_BY_HOTPLUG = 4;
 
+    // The reason code representing the intent action that drives the standby
+    // procedure. The procedure starts either by Intent.ACTION_SCREEN_OFF or
+    // Intent.ACTION_SHUTDOWN.
+    static final int STANDBY_SCREEN_OFF = 0;
+    static final int STANDBY_SHUTDOWN = 1;
+
     /**
      * Interface to report send result.
      */
@@ -143,7 +149,7 @@
             switch (intent.getAction()) {
                 case Intent.ACTION_SCREEN_OFF:
                     if (isPowerOnOrTransient()) {
-                        onStandby();
+                        onStandby(STANDBY_SCREEN_OFF);
                     }
                     break;
                 case Intent.ACTION_SCREEN_ON:
@@ -157,6 +163,11 @@
                         onLanguageChanged(language);
                     }
                     break;
+                case Intent.ACTION_SHUTDOWN:
+                    if (isPowerOnOrTransient()) {
+                        onStandby(STANDBY_SHUTDOWN);
+                    }
+                    break;
             }
         }
 
@@ -510,8 +521,9 @@
                     setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
                     break;
                 case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
-                    if (isTvDeviceEnabled()) {
-                        tv().setAutoDeviceOff(enabled);
+                    for (int type : mLocalDevices) {
+                        HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(type);
+                        localDevice.setAutoDeviceOff(enabled);
                     }
                     // No need to propagate to HAL.
                     break;
@@ -1994,7 +2006,7 @@
     }
 
     @ServiceThreadOnly
-    private void onStandby() {
+    private void onStandby(final int standbyAction) {
         assertRunOnServiceThread();
         if (!canGoToStandby()) return;
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
@@ -2008,7 +2020,7 @@
                 Slog.v(TAG, "On standby-action cleared:" + device.mDeviceType);
                 devices.remove(device);
                 if (devices.isEmpty()) {
-                    onStandbyCompleted();
+                    onStandbyCompleted(standbyAction);
                     // We will not clear local devices here, since some OEM/SOC will keep passing
                     // the received packets until the application processor enters to the sleep
                     // actually.
@@ -2062,7 +2074,7 @@
     }
 
     @ServiceThreadOnly
-    private void onStandbyCompleted() {
+    private void onStandbyCompleted(int standbyAction) {
         assertRunOnServiceThread();
         Slog.v(TAG, "onStandbyCompleted");
 
@@ -2071,7 +2083,7 @@
         }
         mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
         for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
-            device.onStandby(mStandbyMessageReceived);
+            device.onStandby(mStandbyMessageReceived, standbyAction);
         }
         mStandbyMessageReceived = false;
         mAddressAllocated = false;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index aeb6b78..7886b7a 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.server.notification;
 
-import static android.media.AudioAttributes.USAGE_ALARM;
-import static android.media.AudioAttributes.USAGE_MEDIA;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 
@@ -32,6 +30,7 @@
 import android.database.ContentObserver;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
+import android.media.AudioSystem;
 import android.media.VolumePolicy;
 import android.net.Uri;
 import android.os.Bundle;
@@ -41,7 +40,6 @@
 import android.os.UserHandle;
 import android.provider.Settings.Global;
 import android.service.notification.IConditionListener;
-import android.service.notification.NotificationListenerService;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.EventInfo;
 import android.service.notification.ZenModeConfig.ScheduleInfo;
@@ -300,6 +298,7 @@
         if (zen == mZenMode) return false;
         ZenLog.traceSetZenMode(zen, reason);
         mZenMode = zen;
+        updateRingerModeAffectedStreams();
         setZenModeSetting(mZenMode);
         if (setRingerMode) {
             applyZenToRingerMode();
@@ -309,6 +308,12 @@
         return true;
     }
 
+    private void updateRingerModeAffectedStreams() {
+        if (mAudioManager != null) {
+            mAudioManager.updateRingerModeAffectedStreamsInternal();
+        }
+    }
+
     private int computeZenMode(ArraySet<ZenRule> automaticRulesOut) {
         if (mConfig == null) return Global.ZEN_MODE_OFF;
         if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
@@ -334,11 +339,6 @@
         final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
                 || mEffectsSuppressed;
         applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE);
-
-        // alarm/media restrictions
-        final boolean zenNone = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
-        applyRestrictions(zenNone, USAGE_ALARM);
-        applyRestrictions(zenNone, USAGE_MEDIA);
     }
 
     private void applyRestrictions(boolean mute, int usage) {
@@ -523,6 +523,7 @@
                                 && mZenMode != Global.ZEN_MODE_ALARMS) {
                             newZen = Global.ZEN_MODE_ALARMS;
                         }
+                        mPreviousRingerMode = ringerModeOld;
                     }
                     break;
                 case AudioManager.RINGER_MODE_VIBRATE:
@@ -587,6 +588,24 @@
         public boolean canVolumeDownEnterSilent() {
             return mZenMode == Global.ZEN_MODE_OFF;
         }
+
+        @Override
+        public int getRingerModeAffectedStreams(int streams) {
+            // ringtone, notification and system streams are always affected by ringer mode
+            streams |= (1 << AudioSystem.STREAM_RING) |
+                       (1 << AudioSystem.STREAM_NOTIFICATION) |
+                       (1 << AudioSystem.STREAM_SYSTEM);
+
+            // alarm and music streams are only affected by ringer mode when in total silence
+            if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+                streams |= (1 << AudioSystem.STREAM_ALARM) |
+                           (1 << AudioSystem.STREAM_MUSIC);
+            } else {
+                streams &= ~((1 << AudioSystem.STREAM_ALARM) |
+                             (1 << AudioSystem.STREAM_MUSIC));
+            }
+            return streams;
+        }
     }
 
     private final class SettingsObserver extends ContentObserver {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 89ca00e..dcf668d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -127,6 +127,8 @@
     @GuardedBy("mLock")
     private boolean mPermissionsAccepted = false;
     @GuardedBy("mLock")
+    private boolean mRelinquished = false;
+    @GuardedBy("mLock")
     private boolean mDestroyed = false;
 
     private int mFinalStatus;
@@ -557,6 +559,7 @@
             user = new UserHandle(userId);
         }
 
+        mRelinquished = true;
         mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
                 installerPackageName, installerUid, user);
     }
@@ -928,6 +931,10 @@
 
     @Override
     public void abandon() {
+        if (mRelinquished) {
+            Slog.d(TAG, "Ignoring abandon after commit relinquished control");
+            return;
+        }
         destroyInternal();
         dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
     }
@@ -958,8 +965,7 @@
             }
         }
         if (stageDir != null) {
-            FileUtils.deleteContents(stageDir);
-            stageDir.delete();
+            mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
         }
         if (stageCid != null) {
             PackageHelper.destroySdDir(stageCid);
@@ -990,6 +996,7 @@
         pw.printPair("mProgress", mProgress);
         pw.printPair("mSealed", mSealed);
         pw.printPair("mPermissionsAccepted", mPermissionsAccepted);
+        pw.printPair("mRelinquished", mRelinquished);
         pw.printPair("mDestroyed", mDestroyed);
         pw.printPair("mBridges", mBridges.size());
         pw.printPair("mFinalStatus", mFinalStatus);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index decca16..74df0a0 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -150,6 +150,12 @@
     private static final int POWER_HINT_INTERACTION = 2;
     private static final int POWER_HINT_LOW_POWER = 5;
 
+    // Power features defined in hardware/libhardware/include/hardware/power.h.
+    private static final int POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 1;
+
+    // Default setting for double tap to wake.
+    private static final int DEFAULT_DOUBLE_TAP_TO_WAKE = 0;
+
     private final Context mContext;
     private final ServiceThread mHandlerThread;
     private final PowerManagerHandler mHandler;
@@ -339,6 +345,9 @@
     // Otherwise the user won't get much screen on time before dimming occurs.
     private float mMaximumScreenDimRatioConfig;
 
+    // Whether device supports double tap to wake.
+    private boolean mSupportsDoubleTapWakeConfig;
+
     // The screen off timeout setting value in milliseconds.
     private int mScreenOffTimeoutSetting;
 
@@ -430,6 +439,9 @@
     // True if theater mode is enabled
     private boolean mTheaterModeEnabled;
 
+    // True if double tap to wake is enabled
+    private boolean mDoubleTapWakeEnabled;
+
     private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
             = new ArrayList<PowerManagerInternal.LowPowerModeListener>();
 
@@ -440,6 +452,7 @@
     private static native void nativeSetInteractive(boolean enable);
     private static native void nativeSetAutoSuspend(boolean enable);
     private static native void nativeSendPowerHint(int hintId, int data);
+    private static native void nativeSetFeature(int featureId, int data);
 
     public PowerManagerService(Context context) {
         super(context);
@@ -462,6 +475,7 @@
             nativeInit();
             nativeSetAutoSuspend(false);
             nativeSetInteractive(true);
+            nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
         }
     }
 
@@ -580,6 +594,9 @@
             resolver.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.THEATER_MODE_ON),
                     false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.DOUBLE_TAP_TO_WAKE),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
             // Go.
             readConfigurationLocked();
             updateSettingsLocked();
@@ -625,6 +642,8 @@
                 com.android.internal.R.integer.config_maximumScreenDimDuration);
         mMaximumScreenDimRatioConfig = resources.getFraction(
                 com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
+        mSupportsDoubleTapWakeConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_supportDoubleTapWake);
     }
 
     private void updateSettingsLocked() {
@@ -653,6 +672,16 @@
         mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.THEATER_MODE_ON, 0) == 1;
 
+        if (mSupportsDoubleTapWakeConfig) {
+            boolean doubleTapWakeEnabled = Settings.Secure.getIntForUser(resolver,
+                    Settings.Secure.DOUBLE_TAP_TO_WAKE, DEFAULT_DOUBLE_TAP_TO_WAKE,
+                            UserHandle.USER_CURRENT) != 0;
+            if (doubleTapWakeEnabled != mDoubleTapWakeEnabled) {
+                mDoubleTapWakeEnabled = doubleTapWakeEnabled;
+                nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, mDoubleTapWakeEnabled ? 1 : 0);
+            }
+        }
+
         final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
         mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
                 Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
@@ -2610,6 +2639,7 @@
             pw.println("  mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
             pw.println("  mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
             pw.println("  mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+            pw.println("  mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
 
             final int sleepTimeout = getSleepTimeoutLocked();
             final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index ba3ce36..e226e3d 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -84,7 +84,7 @@
         int fontSize = WindowManagerService.getPropertyInt(tokens, 1,
                 TypedValue.COMPLEX_UNIT_DIP, 20, dm);
 
-        mTextPaint = new Paint();
+        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mTextPaint.setTextSize(fontSize);
         mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6bf68e8..57bad51 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -512,7 +512,10 @@
 
     int mLayoutSeq = 0;
 
+    // Last systemUiVisibility we received from status bar.
     int mLastStatusBarVisibility = 0;
+    // Last systemUiVisibility we dispatched to windows.
+    int mLastDispatchedSystemUiVisibility = 0;
 
     // State while inside of layoutAndPlaceSurfacesLocked().
     boolean mFocusMayChange;
@@ -691,6 +694,8 @@
         boolean mObscureApplicationContentOnSecondaryDisplays = false;
 
         float mPreferredRefreshRate = 0;
+
+        int mPreferredModeId = 0;
     }
     final LayoutFields mInnerFields = new LayoutFields();
 
@@ -9713,6 +9718,10 @@
                         && w.mAttrs.preferredRefreshRate != 0) {
                     mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
                 }
+                if (mInnerFields.mPreferredModeId == 0
+                        && w.mAttrs.preferredDisplayModeId != 0) {
+                    mInnerFields.mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+                }
             }
         }
     }
@@ -9846,6 +9855,7 @@
                 // Reset for each display.
                 mInnerFields.mDisplayHasContent = false;
                 mInnerFields.mPreferredRefreshRate = 0;
+                mInnerFields.mPreferredModeId = 0;
 
                 int repeats = 0;
                 do {
@@ -10066,6 +10076,7 @@
 
                 mDisplayManagerInternal.setDisplayProperties(displayId,
                         mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate,
+                        mInnerFields.mPreferredModeId,
                         true /* inTraversal, must call performTraversalInTrans... below */);
 
                 getDisplayContentLocked(displayId).stopDimmingIfNeeded();
@@ -10947,6 +10958,10 @@
 
     // TOOD(multidisplay): StatusBar on multiple screens?
     void updateStatusBarVisibilityLocked(int visibility) {
+        if (mLastDispatchedSystemUiVisibility == visibility) {
+            return;
+        }
+        mLastDispatchedSystemUiVisibility = visibility;
         mInputManager.setSystemUiVisibility(visibility);
         final WindowList windows = getDefaultWindowListLocked();
         final int N = windows.size();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index d6726c1..cdd9503 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1218,6 +1218,10 @@
             mDtDx = 0;
             mDsDy = 0;
             mDtDy = mWin.mGlobalScale;
+            if (appTransformation == null) {
+                mHasClipRect = false;
+                mClipRect.setEmpty();
+            }
         }
     }
 
@@ -1301,7 +1305,10 @@
         clipRect.bottom += attrs.surfaceInsets.bottom;
 
         // If we have an animated clip rect, intersect it with the clip rect.
-        if (mHasClipRect) {
+        // However, the clip rect animation effect should be applied on app windows that inset
+        // decor only. If applying on non-inset decor one, the top region of this window will
+        // be clipped on the end of animation, e.g. dialog activities.
+        if (mHasClipRect && (w.mAttrs.flags & LayoutParams.FLAG_LAYOUT_INSET_DECOR) != 0) {
             // NOTE: We are adding a temporary workaround due to the status bar
             // not always reporting the correct system decor rect. In such
             // cases, we take into account the specified content insets as well.
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 6dcdd9d..1662755 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -156,6 +156,14 @@
     }
 }
 
+static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {
+    int data_param = data;
+
+    if (gPowerModule && gPowerModule->setFeature) {
+        gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param);
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -172,6 +180,8 @@
             (void*) nativeSetAutoSuspend },
     { "nativeSendPowerHint", "(II)V",
             (void*) nativeSendPowerHint },
+    { "nativeSetFeature", "(II)V",
+            (void*) nativeSetFeature },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/telecomm/java/android/telecom/CameraCapabilities.java b/telecomm/java/android/telecom/CameraCapabilities.java
deleted file mode 100644
index 6242956..0000000
--- a/telecomm/java/android/telecom/CameraCapabilities.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.telecom;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents the camera capabilities important to a Video Telephony provider.
- */
-public final class CameraCapabilities implements Parcelable {
-
-    /**
-     * The width of the camera video in pixels.
-     */
-    private final int mWidth;
-
-    /**
-     * The height of the camera video in pixels.
-     */
-    private final int mHeight;
-
-    /**
-     * Whether the camera supports zoom.
-     */
-    private final boolean mZoomSupported;
-
-    /**
-     * The maximum zoom supported by the camera.
-     */
-    private final float mMaxZoom;
-
-    /**
-     * Create a call camera capabilities instance.
-     *
-     * @param width The width of the camera video (in pixels).
-     * @param height The height of the camera video (in pixels).
-     */
-    public CameraCapabilities(int width, int height) {
-        this(width, height, false, 1.0f);
-    }
-
-    /**
-     * Create a call camera capabilities instance that optionally
-     * supports zoom.
-     *
-     * @param width The width of the camera video (in pixels).
-     * @param height The height of the camera video (in pixels).
-     * @param zoomSupported True when camera supports zoom.
-     * @param maxZoom Maximum zoom supported by camera.
-     * @hide
-     */
-    public CameraCapabilities(int width, int height, boolean zoomSupported, float maxZoom) {
-        mWidth = width;
-        mHeight = height;
-        mZoomSupported = zoomSupported;
-        mMaxZoom = maxZoom;
-    }
-
-    /**
-     * Responsible for creating CallCameraCapabilities objects from deserialized Parcels.
-     **/
-    public static final Parcelable.Creator<CameraCapabilities> CREATOR =
-            new Parcelable.Creator<CameraCapabilities> () {
-                /**
-                 * Creates a CallCameraCapabilities instances from a parcel.
-                 *
-                 * @param source The parcel.
-                 * @return The CallCameraCapabilities.
-                 */
-                @Override
-                public CameraCapabilities createFromParcel(Parcel source) {
-                    int width = source.readInt();
-                    int height = source.readInt();
-                    boolean supportsZoom = source.readByte() != 0;
-                    float maxZoom = source.readFloat();
-
-                    return new CameraCapabilities(width, height, supportsZoom, maxZoom);
-                }
-
-                @Override
-                public CameraCapabilities[] newArray(int size) {
-                    return new CameraCapabilities[size];
-                }
-            };
-
-    /**
-     * Describe the kinds of special objects contained in this Parcelable's
-     * marshalled representation.
-     *
-     * @return a bitmask indicating the set of special object types marshalled
-     * by the Parcelable.
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Flatten this object in to a Parcel.
-     *
-     * @param dest  The Parcel in which the object should be written.
-     * @param flags Additional flags about how the object should be written.
-     *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
-     */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(getWidth());
-        dest.writeInt(getHeight());
-        dest.writeByte((byte) (isZoomSupported() ? 1 : 0));
-        dest.writeFloat(getMaxZoom());
-    }
-
-    /**
-     * The width of the camera video in pixels.
-     */
-    public int getWidth() {
-        return mWidth;
-    }
-
-    /**
-     * The height of the camera video in pixels.
-     */
-    public int getHeight() {
-        return mHeight;
-    }
-
-    /**
-     * Whether the camera supports zoom.
-     * @hide
-     */
-    public boolean isZoomSupported() {
-        return mZoomSupported;
-    }
-
-    /**
-     * The maximum zoom supported by the camera.
-     * @hide
-     */
-    public float getMaxZoom() {
-        return mMaxZoom;
-    }
-}
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index e682697..e2971f9 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.telecom.Connection.VideoProvider;
 
 import java.util.ArrayList;
@@ -116,7 +117,7 @@
     }
 
     /**
-     * Returns the capabilities of a conference. See {@code CAPABILITY_*} constants in class
+     * Returns the capabilities of the conference. See {@code CAPABILITY_*} constants in class
      * {@link Connection} for valid values.
      *
      * @return A bitmask of the capabilities of the conference call.
@@ -458,7 +459,9 @@
      * the connection from which the conference will retrieve its current state.
      *
      * @return The primary connection.
+     * @hide
      */
+    @SystemApi
     public Connection getPrimaryConnection() {
         if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) {
             return null;
@@ -467,22 +470,42 @@
     }
 
     /**
-     * Sets the connect time of the {@code Conference}.
-     *
-     * @param connectTimeMillis The connection time, in milliseconds.
+     * @hide
+     * @deprecated Use {@link #setConnectionTime}.
      */
-    public void setConnectTimeMillis(long connectTimeMillis) {
-        mConnectTimeMillis = connectTimeMillis;
+    @Deprecated
+    @SystemApi
+    public final void setConnectTimeMillis(long connectTimeMillis) {
+        setConnectionTime(connectTimeMillis);
     }
 
     /**
-     * Retrieves the connect time of the {@code Conference}, if specified.  A value of
+     * Sets the connection start time of the {@code Conference}.
+     *
+     * @param connectionTimeMillis The connection time, in milliseconds.
+     */
+    public final void setConnectionTime(long connectionTimeMillis) {
+        mConnectTimeMillis = connectionTimeMillis;
+    }
+
+    /**
+     * @hide
+     * @deprecated Use {@link #getConnectionTime}.
+     */
+    @Deprecated
+    @SystemApi
+    public final long getConnectTimeMillis() {
+        return getConnectionTime();
+    }
+
+    /**
+     * Retrieves the connection start time of the {@code Conference}, if specified.  A value of
      * {@link #CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the start time
      * of the conference.
      *
-     * @return The time the {@code Conference} has been connected.
+     * @return The time at which the {@code Conference} was connected.
      */
-    public final long getConnectTimeMillis() {
+    public final long getConnectionTime() {
         return mConnectTimeMillis;
     }
 
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 0bf9118..5076c38 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -742,7 +742,7 @@
          *
          * @param cameraCapabilities The changed camera capabilities.
          */
-        public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
+        public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
             if (mVideoCallbacks != null) {
                 try {
                     for (IVideoCallback callback : mVideoCallbacks.values()) {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 3cb4e87..63a416b 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -546,7 +546,8 @@
              *
              * @param cameraCapabilities The changed camera capabilities.
              */
-            public abstract void onCameraCapabilitiesChanged(CameraCapabilities cameraCapabilities);
+            public abstract void onCameraCapabilitiesChanged(
+                    VideoProfile.CameraCapabilities cameraCapabilities);
         }
     }
 }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index bab460d..86475b1 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -47,7 +47,7 @@
  * should supply a valid {@link PhoneAccountHandle} that references the connection service
  * implementation Telecom will use to interact with the app.
  */
-public class PhoneAccount implements Parcelable {
+public final class PhoneAccount implements Parcelable {
 
     /**
      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 60917b2..6dc6e9c 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -35,7 +35,7 @@
  *
  * See {@link PhoneAccount}, {@link TelecomManager}.
  */
-public class PhoneAccountHandle implements Parcelable {
+public final class PhoneAccountHandle implements Parcelable {
     private final ComponentName mComponentName;
     private final String mId;
     private final UserHandle mUserHandle;
diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java
index a76bf59..b59584b 100644
--- a/telecomm/java/android/telecom/RemoteConference.java
+++ b/telecomm/java/android/telecom/RemoteConference.java
@@ -29,7 +29,10 @@
 import java.util.concurrent.CopyOnWriteArraySet;
 
 /**
- * Represents a conference call which can contain any number of {@link Connection} objects.
+ * A conference provided to a {@link ConnectionService} by another {@code ConnectionService}
+ * running in a different process.
+ *
+ * @see ConnectionService#onRemoteConferenceAdded
  */
 public final class RemoteConference {
 
@@ -62,18 +65,18 @@
     private DisconnectCause mDisconnectCause;
     private int mConnectionCapabilities;
 
-    /** {@hide} */
+    /** @hide */
     RemoteConference(String id, IConnectionService connectionService) {
         mId = id;
         mConnectionService = connectionService;
     }
 
-    /** {@hide} */
+    /** @hide */
     String getId() {
         return mId;
     }
 
-    /** {@hide} */
+    /** @hide */
     void setDestroyed() {
         for (RemoteConnection connection : mChildConnections) {
             connection.setConference(null);
@@ -90,7 +93,7 @@
         }
     }
 
-    /** {@hide} */
+    /** @hide */
     void setState(final int newState) {
         if (newState != Connection.STATE_ACTIVE &&
                 newState != Connection.STATE_HOLDING &&
@@ -116,7 +119,7 @@
         }
     }
 
-    /** {@hide} */
+    /** @hide */
     void addConnection(final RemoteConnection connection) {
         if (!mChildConnections.contains(connection)) {
             mChildConnections.add(connection);
@@ -134,7 +137,7 @@
         }
     }
 
-    /** {@hide} */
+    /** @hide */
     void removeConnection(final RemoteConnection connection) {
         if (mChildConnections.contains(connection)) {
             mChildConnections.remove(connection);
@@ -152,7 +155,7 @@
         }
     }
 
-    /** {@hide} */
+    /** @hide */
     void setConnectionCapabilities(final int connectionCapabilities) {
         if (mConnectionCapabilities != connectionCapabilities) {
             mConnectionCapabilities = connectionCapabilities;
@@ -187,7 +190,7 @@
         }
     }
 
-    /** {@hide} */
+    /** @hide */
     void setDisconnected(final DisconnectCause disconnectCause) {
         if (mState != Connection.STATE_DISCONNECTED) {
             mDisconnectCause = disconnectCause;
@@ -205,18 +208,37 @@
         }
     }
 
+    /**
+     * Returns the list of {@link RemoteConnection}s contained in this conference.
+     *
+     * @return A list of child connections.
+     */
     public final List<RemoteConnection> getConnections() {
         return mUnmodifiableChildConnections;
     }
 
+    /**
+     * Gets the state of the conference call. See {@link Connection} for valid values.
+     *
+     * @return A constant representing the state the conference call is currently in.
+     */
     public final int getState() {
         return mState;
     }
 
+    /**
+     * Returns the capabilities of the conference. See {@code CAPABILITY_*} constants in class
+     * {@link Connection} for valid values.
+     *
+     * @return A bitmask of the capabilities of the conference call.
+     */
     public final int getConnectionCapabilities() {
         return mConnectionCapabilities;
     }
 
+    /**
+     * Disconnects the conference call as well as the child {@link RemoteConnection}s.
+     */
     public void disconnect() {
         try {
             mConnectionService.disconnect(mId);
@@ -224,6 +246,13 @@
         }
     }
 
+    /**
+     * Removes the specified {@link RemoteConnection} from the conference. This causes the
+     * {@link RemoteConnection} to become a standalone connection. This is a no-op if the
+     * {@link RemoteConnection} does not belong to this conference.
+     *
+     * @param connection The remote-connection to remove.
+     */
     public void separate(RemoteConnection connection) {
         if (mChildConnections.contains(connection)) {
             try {
@@ -233,6 +262,16 @@
         }
     }
 
+    /**
+     * Merges all {@link RemoteConnection}s of this conference into a single call. This should be
+     * invoked only if the conference contains the capability
+     * {@link Connection#CAPABILITY_MERGE_CONFERENCE}, otherwise it is a no-op. The presence of said
+     * capability indicates that the connections of this conference, despite being part of the
+     * same conference object, are yet to have their audio streams merged; this is a common pattern
+     * for CDMA conference calls, but the capability is not used for GSM and SIP conference calls.
+     * Invoking this method will cause the unmerged child connections to merge their audio
+     * streams.
+     */
     public void merge() {
         try {
             mConnectionService.mergeConference(mId);
@@ -240,6 +279,15 @@
         }
     }
 
+    /**
+     * Swaps the active audio stream between the conference's child {@link RemoteConnection}s.
+     * This should be invoked only if the conference contains the capability
+     * {@link Connection#CAPABILITY_SWAP_CONFERENCE}, otherwise it is a no-op. This is only used by
+     * {@link ConnectionService}s that create conferences for connections that do not yet have
+     * their audio streams merged; this is a common pattern for CDMA conference calls, but the
+     * capability is not used for GSM and SIP conference calls. Invoking this method will change the
+     * active audio stream to a different child connection.
+     */
     public void swap() {
         try {
             mConnectionService.swapConference(mId);
@@ -247,6 +295,9 @@
         }
     }
 
+    /**
+     * Puts the conference on hold.
+     */
     public void hold() {
         try {
             mConnectionService.hold(mId);
@@ -254,6 +305,9 @@
         }
     }
 
+    /**
+     * Unholds the conference call.
+     */
     public void unhold() {
         try {
             mConnectionService.unhold(mId);
@@ -261,10 +315,22 @@
         }
     }
 
+    /**
+     * Returns the {@link DisconnectCause} for the conference if it is in the state
+     * {@link Connection#STATE_DISCONNECTED}. If the conference is not disconnected, this will
+     * return null.
+     *
+     * @return The disconnect cause.
+     */
     public DisconnectCause getDisconnectCause() {
         return mDisconnectCause;
     }
 
+    /**
+     * Requests that the conference start playing the specified DTMF tone.
+     *
+     * @param digit The digit for which to play a DTMF tone.
+     */
     public void playDtmfTone(char digit) {
         try {
             mConnectionService.playDtmfTone(mId, digit);
@@ -272,6 +338,11 @@
         }
     }
 
+    /**
+     * Stops the most recent request to play a DTMF tone.
+     *
+     * @see #playDtmfTone
+     */
     public void stopDtmfTone() {
         try {
             mConnectionService.stopDtmfTone(mId);
@@ -279,6 +350,12 @@
         }
     }
 
+    /**
+     * Request to change the conference's audio routing to the specified state. The specified state
+     * can include audio routing (Bluetooth, Speaker, etc) and muting state.
+     *
+     * @see android.telecom.AudioState
+     */
     public void setAudioState(AudioState state) {
         try {
             mConnectionService.onAudioStateChanged(mId, state);
@@ -286,14 +363,31 @@
         }
     }
 
+    /**
+     * Returns a list of independent connections that can me merged with this conference.
+     *
+     * @return A list of conferenceable connections.
+     */
     public List<RemoteConnection> getConferenceableConnections() {
         return mUnmodifiableConferenceableConnections;
     }
 
+    /**
+     * Register a callback through which to receive state updates for this conference.
+     *
+     * @param callback The callback to notify of state changes.
+     */
     public final void registerCallback(Callback callback) {
         registerCallback(callback, new Handler());
     }
 
+    /**
+     * Registers a callback through which to receive state updates for this conference.
+     * Callbacks will be notified using the specified handler, if provided.
+     *
+     * @param callback The callback to notify of state changes.
+     * @param handler The handler on which to execute the callbacks.
+     */
     public final void registerCallback(Callback callback, Handler handler) {
         unregisterCallback(callback);
         if (callback != null && handler != null) {
@@ -301,6 +395,13 @@
         }
     }
 
+    /**
+     * Unregisters a previously registered callback.
+     *
+     * @see #registerCallback
+     *
+     * @param callback The callback to unregister.
+     */
     public final void unregisterCallback(Callback callback) {
         if (callback != null) {
             for (CallbackRecord<Callback> record : mCallbackRecords) {
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 9ca9f316..f2e6bcb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -220,7 +220,7 @@
 
             public void onCameraCapabilitiesChanged(
                     VideoProvider videoProvider,
-                    CameraCapabilities cameraCapabilities) {}
+                    VideoProfile.CameraCapabilities cameraCapabilities) {}
 
             public void onVideoQualityChanged(VideoProvider videoProvider, int videoQuality) {}
         }
@@ -267,7 +267,8 @@
             }
 
             @Override
-            public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
+            public void changeCameraCapabilities(
+                    VideoProfile.CameraCapabilities cameraCapabilities) {
                 for (Listener l : mListeners) {
                     l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities);
                 }
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 331f57e..5352dfc 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -98,7 +98,7 @@
         }
 
         @Override
-        public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
+        public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
             mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
                     cameraCapabilities).sendToTarget();
         }
@@ -160,7 +160,7 @@
                     break;
                 case MSG_CHANGE_CAMERA_CAPABILITIES:
                     mCallback.onCameraCapabilitiesChanged(
-                            (CameraCapabilities) msg.obj);
+                            (VideoProfile.CameraCapabilities) msg.obj);
                     break;
                 case MSG_CHANGE_VIDEO_QUALITY:
                     mVideoQuality = msg.arg1;
diff --git a/telecomm/java/android/telecom/VideoCallbackServant.java b/telecomm/java/android/telecom/VideoCallbackServant.java
index 1123621..1fbad224 100644
--- a/telecomm/java/android/telecom/VideoCallbackServant.java
+++ b/telecomm/java/android/telecom/VideoCallbackServant.java
@@ -98,7 +98,7 @@
                     break;
                 }
                 case MSG_CHANGE_CAMERA_CAPABILITIES: {
-                    mDelegate.changeCameraCapabilities((CameraCapabilities) msg.obj);
+                    mDelegate.changeCameraCapabilities((VideoProfile.CameraCapabilities) msg.obj);
                     break;
                 }
                 case MSG_CHANGE_VIDEO_QUALITY: {
@@ -148,7 +148,8 @@
         }
 
         @Override
-        public void changeCameraCapabilities(CameraCapabilities cameraCapabilities)
+        public void changeCameraCapabilities(
+                VideoProfile.CameraCapabilities cameraCapabilities)
                 throws RemoteException {
             mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, cameraCapabilities)
                     .sendToTarget();
diff --git a/telecomm/java/android/telecom/VideoProfile.aidl b/telecomm/java/android/telecom/VideoProfile.aidl
index 091b569..0b32721 100644
--- a/telecomm/java/android/telecom/VideoProfile.aidl
+++ b/telecomm/java/android/telecom/VideoProfile.aidl
@@ -21,3 +21,4 @@
  * {@hide}
  */
 parcelable VideoProfile;
+parcelable VideoProfile.CameraCapabilities;
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 902fddb..7ac4090 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -278,4 +278,142 @@
             return sb.toString();
         }
     }
+
+    /**
+     * Represents the camera capabilities important to a Video Telephony provider.
+     */
+    public static final class CameraCapabilities implements Parcelable {
+
+        /**
+         * The width of the camera video in pixels.
+         */
+        private final int mWidth;
+
+        /**
+         * The height of the camera video in pixels.
+         */
+        private final int mHeight;
+
+        /**
+         * Whether the camera supports zoom.
+         */
+        private final boolean mZoomSupported;
+
+        /**
+         * The maximum zoom supported by the camera.
+         */
+        private final float mMaxZoom;
+
+        /**
+         * Create a call camera capabilities instance.
+         *
+         * @param width The width of the camera video (in pixels).
+         * @param height The height of the camera video (in pixels).
+         */
+        public CameraCapabilities(int width, int height) {
+            this(width, height, false, 1.0f);
+        }
+
+        /**
+         * Create a call camera capabilities instance that optionally
+         * supports zoom.
+         *
+         * @param width The width of the camera video (in pixels).
+         * @param height The height of the camera video (in pixels).
+         * @param zoomSupported True when camera supports zoom.
+         * @param maxZoom Maximum zoom supported by camera.
+         * @hide
+         */
+        public CameraCapabilities(int width, int height, boolean zoomSupported, float maxZoom) {
+            mWidth = width;
+            mHeight = height;
+            mZoomSupported = zoomSupported;
+            mMaxZoom = maxZoom;
+        }
+
+        /**
+         * Responsible for creating CallCameraCapabilities objects from deserialized Parcels.
+         **/
+        public static final Parcelable.Creator<CameraCapabilities> CREATOR =
+                new Parcelable.Creator<CameraCapabilities> () {
+                    /**
+                     * Creates a CallCameraCapabilities instances from a parcel.
+                     *
+                     * @param source The parcel.
+                     * @return The CallCameraCapabilities.
+                     */
+                    @Override
+                    public CameraCapabilities createFromParcel(Parcel source) {
+                        int width = source.readInt();
+                        int height = source.readInt();
+                        boolean supportsZoom = source.readByte() != 0;
+                        float maxZoom = source.readFloat();
+
+                        return new CameraCapabilities(width, height, supportsZoom, maxZoom);
+                    }
+
+                    @Override
+                    public CameraCapabilities[] newArray(int size) {
+                        return new CameraCapabilities[size];
+                    }
+                };
+
+        /**
+         * Describe the kinds of special objects contained in this Parcelable's
+         * marshalled representation.
+         *
+         * @return a bitmask indicating the set of special object types marshalled
+         * by the Parcelable.
+         */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        /**
+         * Flatten this object in to a Parcel.
+         *
+         * @param dest  The Parcel in which the object should be written.
+         * @param flags Additional flags about how the object should be written.
+         *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+         */
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(getWidth());
+            dest.writeInt(getHeight());
+            dest.writeByte((byte) (isZoomSupported() ? 1 : 0));
+            dest.writeFloat(getMaxZoom());
+        }
+
+        /**
+         * The width of the camera video in pixels.
+         */
+        public int getWidth() {
+            return mWidth;
+        }
+
+        /**
+         * The height of the camera video in pixels.
+         */
+        public int getHeight() {
+            return mHeight;
+        }
+
+        /**
+         * Whether the camera supports zoom.
+         * @hide
+         */
+        public boolean isZoomSupported() {
+            return mZoomSupported;
+        }
+
+        /**
+         * The maximum zoom supported by the camera.
+         * @hide
+         */
+        public float getMaxZoom() {
+            return mMaxZoom;
+        }
+    }
+
 }
diff --git a/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl b/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl
index 59f8f0c..cdfad02 100644
--- a/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl
+++ b/telecomm/java/com/android/internal/telecom/IVideoCallback.aidl
@@ -16,7 +16,6 @@
 
 package com.android.internal.telecom;
 
-import android.telecom.CameraCapabilities;
 import android.telecom.VideoProfile;
 
  /**
@@ -41,7 +40,7 @@
 
     void changeCallDataUsage(long dataUsage);
 
-    void changeCameraCapabilities(in CameraCapabilities cameraCapabilities);
+    void changeCameraCapabilities(in VideoProfile.CameraCapabilities cameraCapabilities);
 
     void changeVideoQuality(int videoQuality);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
index be8751b..9499c9f 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
@@ -16,7 +16,6 @@
 
 package com.android.ims.internal;
 
-import android.telecom.CameraCapabilities;
 import android.telecom.VideoProfile;
 
 /**
@@ -43,7 +42,7 @@
 
     void changeCallDataUsage(long dataUsage);
 
-    void changeCameraCapabilities(in CameraCapabilities cameraCapabilities);
+    void changeCameraCapabilities(in VideoProfile.CameraCapabilities cameraCapabilities);
 
     void changeVideoQuality(int videoQuality);
 }
diff --git a/tests/LockTaskTests/AndroidManifest.xml b/tests/LockTaskTests/AndroidManifest.xml
index f88744e..e349c92 100644
--- a/tests/LockTaskTests/AndroidManifest.xml
+++ b/tests/LockTaskTests/AndroidManifest.xml
@@ -29,28 +29,28 @@
             android:label="@string/title_activity_default"
             android:taskAffinity=""
             android:documentLaunchMode="always"
-            android:lockTaskMode="lockTaskModeDefault" >
+            android:lockTaskMode="normal" >
         </activity>
         <activity
             android:name="com.google.android.example.locktasktests.LockTaskNeverActivity"
             android:label="@string/title_activity_never"
             android:taskAffinity=""
             android:documentLaunchMode="always"
-            android:lockTaskMode="lockTaskModeNever" >
+            android:lockTaskMode="never" >
         </activity>
         <activity
             android:name="com.google.android.example.locktasktests.LockWhitelistedActivity"
             android:label="@string/title_activity_whitelist"
             android:taskAffinity=""
             android:documentLaunchMode="always"
-            android:lockTaskMode="lockTaskModeIfWhitelisted" >
+            android:lockTaskMode="if_whitelisted" >
         </activity>
         <activity
             android:name="com.google.android.example.locktasktests.LockAtLaunchActivity"
             android:label="@string/title_activity_always"
             android:taskAffinity=""
             android:documentLaunchMode="always"
-            android:lockTaskMode="lockTaskModeAlways" >
+            android:lockTaskMode="always" >
         </activity>
     </application>
 
diff --git a/tests/LockTaskTests/res/values/strings.xml b/tests/LockTaskTests/res/values/strings.xml
index 61c029f..3bcae80 100644
--- a/tests/LockTaskTests/res/values/strings.xml
+++ b/tests/LockTaskTests/res/values/strings.xml
@@ -7,16 +7,17 @@
     <string name="title_activity_whitelist">LockWhitelistedActivity</string>
     <string name="title_activity_always">LockAtLaunchActivity</string>
     <string name="launch_default">android:lockTaskMode=\n
-            \"lockTaskModeDefault\"\n
+            \"default\"\n
             Pinnable from Overview.</string>
     <string name="launch_never">android:lockTaskMode=\n
-            \"lockTaskModeNever\"\n
+            \"never\"\n
             Not Lockable or Pinnable.</string>
-    <string name="launch_whitelist">android:lockTaskMode=\n\"lockTaskModeIfWhitelisted\"\n
+    <string name="launch_whitelist">android:lockTaskMode=\n
+            \"if_whitelisted\"\n
             Lockable if whitelisted, Pinnable.\n
             Use SampleDeviceOwner app to set whitelist.</string>
     <string name="launch_always">android:lockTaskMode=\n
-            \"lockTaskModeAlways\"\n
+            \"always\"\n
             Launches into lock mode.</string>
     <string name="launch_main">launch MainActivity (as activity)"</string>
     <string name="try_lock">Call startLockMode()</string>
diff --git a/tests/LockTaskTests/src/com/google/android/example/locktasktests/MainActivity.java b/tests/LockTaskTests/src/com/google/android/example/locktasktests/MainActivity.java
index c2275c8..3e4f8ee 100644
--- a/tests/LockTaskTests/src/com/google/android/example/locktasktests/MainActivity.java
+++ b/tests/LockTaskTests/src/com/google/android/example/locktasktests/MainActivity.java
@@ -6,26 +6,50 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
 import android.view.View;
 
 public class MainActivity extends Activity {
 
     private final static String TAG = "LockTaskTests";
+    Runnable mBackgroundPolling;
+    boolean mRunning;
+    Handler mHandler;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
+        mBackgroundPolling = new Runnable() {
+            // Poll lock task state and set background pink if locked, otherwise white.
+            @Override
+            public void run() {
+                if (!mRunning) {
+                    return;
+                }
+                ActivityManager activityManager =
+                        (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+                final int color = activityManager.getLockTaskModeState() !=
+                        ActivityManager.LOCK_TASK_MODE_NONE ? 0xFFFFC0C0 : 0xFFFFFFFF;
+                findViewById(R.id.root_launch).setBackgroundColor(color);
+                mHandler.postDelayed(this, 500);
+            }
+        };
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        ActivityManager activityManager =
-                (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-        final int color = activityManager.getLockTaskModeState() !=
-                ActivityManager.LOCK_TASK_MODE_NONE ? 0xFFFFC0C0 : 0xFFFFFFFF;
-        findViewById(R.id.root_launch).setBackgroundColor(color);
+        mRunning = true;
+        mBackgroundPolling.run();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mRunning = false;
     }
 
     public void onButtonPressed(View v) {
diff --git a/tests/notification/Android.mk b/tests/notification/Android.mk
new file mode 100644
index 0000000..0669553
--- /dev/null
+++ b/tests/notification/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := NotificationTests
+
+LOCAL_SDK_VERSION := 21
+
+include $(BUILD_PACKAGE)
+
diff --git a/tests/notification/AndroidManifest.xml b/tests/notification/AndroidManifest.xml
new file mode 100644
index 0000000..7cee00a7
--- /dev/null
+++ b/tests/notification/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.frameworks.tests.notification"
+    >
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.frameworks.tests.notification"
+        android:label="Frameworks Notification Tests" />
+</manifest>
diff --git a/tests/notification/res/drawable-nodpi/arubin_hed.jpeg b/tests/notification/res/drawable-nodpi/arubin_hed.jpeg
new file mode 100644
index 0000000..c6d8ae9
--- /dev/null
+++ b/tests/notification/res/drawable-nodpi/arubin_hed.jpeg
Binary files differ
diff --git a/tests/notification/res/drawable-nodpi/bucket.png b/tests/notification/res/drawable-nodpi/bucket.png
new file mode 100644
index 0000000..c865649
--- /dev/null
+++ b/tests/notification/res/drawable-nodpi/bucket.png
Binary files differ
diff --git a/tests/notification/res/drawable-nodpi/matias_hed.jpg b/tests/notification/res/drawable-nodpi/matias_hed.jpg
new file mode 100644
index 0000000..8cc3081
--- /dev/null
+++ b/tests/notification/res/drawable-nodpi/matias_hed.jpg
Binary files differ
diff --git a/tests/notification/res/drawable-nodpi/page_hed.jpg b/tests/notification/res/drawable-nodpi/page_hed.jpg
new file mode 100644
index 0000000..ea950c8
--- /dev/null
+++ b/tests/notification/res/drawable-nodpi/page_hed.jpg
Binary files differ
diff --git a/tests/notification/res/drawable-nodpi/romainguy_hed.jpg b/tests/notification/res/drawable-nodpi/romainguy_hed.jpg
new file mode 100644
index 0000000..5b7643e
--- /dev/null
+++ b/tests/notification/res/drawable-nodpi/romainguy_hed.jpg
Binary files differ
diff --git a/tests/notification/res/drawable-nodpi/romainguy_rockaway.jpg b/tests/notification/res/drawable-nodpi/romainguy_rockaway.jpg
new file mode 100644
index 0000000..68473ba
--- /dev/null
+++ b/tests/notification/res/drawable-nodpi/romainguy_rockaway.jpg
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/add.png b/tests/notification/res/drawable-xhdpi/add.png
new file mode 100644
index 0000000..7226b3d
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/add.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/ic_dial_action_call.png b/tests/notification/res/drawable-xhdpi/ic_dial_action_call.png
new file mode 100644
index 0000000..ca20a91
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/ic_dial_action_call.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/ic_end_call.png b/tests/notification/res/drawable-xhdpi/ic_end_call.png
new file mode 100644
index 0000000..c464a6d
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/ic_end_call.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/ic_media_next.png b/tests/notification/res/drawable-xhdpi/ic_media_next.png
new file mode 100644
index 0000000..4def965
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/ic_media_next.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/ic_menu_upload.png b/tests/notification/res/drawable-xhdpi/ic_menu_upload.png
new file mode 100644
index 0000000..f1438ed
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/ic_menu_upload.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/icon.png b/tests/notification/res/drawable-xhdpi/icon.png
new file mode 100644
index 0000000..189e85b
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/icon.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_alarm.png b/tests/notification/res/drawable-xhdpi/stat_notify_alarm.png
new file mode 100644
index 0000000..658d04f
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_alarm.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_calendar.png b/tests/notification/res/drawable-xhdpi/stat_notify_calendar.png
new file mode 100644
index 0000000..5ae7782
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_calendar.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_email.png b/tests/notification/res/drawable-xhdpi/stat_notify_email.png
new file mode 100644
index 0000000..23c4672
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_email.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_missed_call.png b/tests/notification/res/drawable-xhdpi/stat_notify_missed_call.png
new file mode 100644
index 0000000..8719eff
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_sms.png b/tests/notification/res/drawable-xhdpi/stat_notify_sms.png
new file mode 100644
index 0000000..323cb3d
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_sms.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_snooze.png b/tests/notification/res/drawable-xhdpi/stat_notify_snooze.png
new file mode 100644
index 0000000..26dcda35
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_snooze.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_snooze_longer.png b/tests/notification/res/drawable-xhdpi/stat_notify_snooze_longer.png
new file mode 100644
index 0000000..b8b2f8a
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_snooze_longer.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_notify_talk_text.png b/tests/notification/res/drawable-xhdpi/stat_notify_talk_text.png
new file mode 100644
index 0000000..12cae9f
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_notify_talk_text.png
Binary files differ
diff --git a/tests/notification/res/drawable-xhdpi/stat_sys_phone_call.png b/tests/notification/res/drawable-xhdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..db42b7c
--- /dev/null
+++ b/tests/notification/res/drawable-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/tests/notification/res/layout/full_screen.xml b/tests/notification/res/layout/full_screen.xml
new file mode 100644
index 0000000..6ff7552
--- /dev/null
+++ b/tests/notification/res/layout/full_screen.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:src="@drawable/page_hed"
+        android:onClick="dismiss"
+        />
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/notification/res/layout/main.xml b/tests/notification/res/layout/main.xml
new file mode 100644
index 0000000..f5a740f
--- /dev/null
+++ b/tests/notification/res/layout/main.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+    <LinearLayout android:id="@+id/linearLayout1" android:orientation="vertical" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_width="match_parent" android:layout_margin="35dp">
+        <Button android:id="@+id/button1" android:text="@string/post_button_label" android:layout_height="wrap_content" android:layout_width="match_parent" android:onClick="doPost"></Button>
+        <Button android:id="@+id/button2" android:text="@string/remove_button_label" android:layout_height="wrap_content" android:layout_width="match_parent" android:onClick="doRemove"></Button>
+    </LinearLayout>
+</FrameLayout>
diff --git a/tests/notification/res/values/dimens.xml b/tests/notification/res/values/dimens.xml
new file mode 100644
index 0000000..21e7bc3
--- /dev/null
+++ b/tests/notification/res/values/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2012, 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.
+*/
+-->
+<resources>
+    <!-- The width of the big icons in notifications. -->
+    <dimen name="notification_large_icon_width">64dp</dimen>
+    <!-- The width of the big icons in notifications. -->
+    <dimen name="notification_large_icon_height">64dp</dimen>
+</resources>
diff --git a/tests/notification/res/values/strings.xml b/tests/notification/res/values/strings.xml
new file mode 100644
index 0000000..80bf103
--- /dev/null
+++ b/tests/notification/res/values/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="hello">Hello World, NotificationShowcaseActivity!</string>
+    <string name="app_name">NotificationShowcase</string>
+    <string name="post_button_label">Post Notifications</string>
+    <string name="remove_button_label">Remove Notifications</string>
+    <string name="answered">call answered</string>
+    <string name="ignored">call ignored</string>
+    <string name="full_screen_name">Full Screen Activity</string>
+</resources>
diff --git a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
new file mode 100644
index 0000000..7cda977
--- /dev/null
+++ b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
@@ -0,0 +1,494 @@
+/*
+ * 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 android.app;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.SystemClock;
+import android.provider.ContactsContract;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+import java.lang.reflect.Method;
+import java.lang.InterruptedException;
+import java.lang.NoSuchMethodError;
+import java.lang.NoSuchMethodException;
+import java.util.ArrayList;
+
+import com.android.frameworks.tests.notification.R;
+
+public class NotificationTests extends AndroidTestCase {
+    private static final String TAG = "NOTEST";
+    public static void L(String msg, Object... args) {
+        Log.v(TAG, (args == null || args.length == 0) ? msg : String.format(msg, args));
+    }
+
+    public static final String ACTION_CREATE = "create";
+    public static final int NOTIFICATION_ID = 31338;
+
+    public static final boolean SHOW_PHONE_CALL = false;
+    public static final boolean SHOW_INBOX = true;
+    public static final boolean SHOW_BIG_TEXT = true;
+    public static final boolean SHOW_BIG_PICTURE = true;
+    public static final boolean SHOW_MEDIA = true;
+    public static final boolean SHOW_STOPWATCH = false;
+    public static final boolean SHOW_SOCIAL = false;
+    public static final boolean SHOW_CALENDAR = false;
+    public static final boolean SHOW_PROGRESS = false;
+
+    private static Bitmap getBitmap(Context context, int resId) {
+        int largeIconWidth = (int) context.getResources()
+                .getDimension(R.dimen.notification_large_icon_width);
+        int largeIconHeight = (int) context.getResources()
+                .getDimension(R.dimen.notification_large_icon_height);
+        Drawable d = context.getResources().getDrawable(resId);
+        Bitmap b = Bitmap.createBitmap(largeIconWidth, largeIconHeight, Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        d.setBounds(0, 0, largeIconWidth, largeIconHeight);
+        d.draw(c);
+        return b;
+    }
+
+    private static PendingIntent makeEmailIntent(Context context, String who) {
+        final Intent intent = new Intent(android.content.Intent.ACTION_SENDTO,
+                Uri.parse("mailto:" + who));
+        return PendingIntent.getActivity(
+                context, 0, intent,
+                PendingIntent.FLAG_CANCEL_CURRENT);
+    }
+
+    static final String[] LINES = new String[] {
+            "Uh oh",
+            "Getting kicked out of this room",
+            "I'll be back in 5-10 minutes.",
+            "And now \u2026 I have to find my shoes. \uD83D\uDC63",
+            "\uD83D\uDC5F \uD83D\uDC5F",
+            "\uD83D\uDC60 \uD83D\uDC60",
+    };
+    static final int MAX_LINES = 5;
+    public static Notification makeBigTextNotification(Context context, int update, int id,
+            long when) {
+        String personUri = null;
+        /*
+        Cursor c = null;
+        try {
+            String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY };
+            String selections = ContactsContract.Contacts.DISPLAY_NAME + " = 'Mike Cleron'";
+            final ContentResolver contentResolver = context.getContentResolver();
+            c = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,
+                    projection, selections, null, null);
+            if (c != null && c.getCount() > 0) {
+                c.moveToFirst();
+                int lookupIdx = c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
+                int idIdx = c.getColumnIndex(ContactsContract.Contacts._ID);
+                String lookupKey = c.getString(lookupIdx);
+                long contactId = c.getLong(idIdx);
+                Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
+                personUri = lookupUri.toString();
+            }
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        if (TextUtils.isEmpty(personUri)) {
+            Log.w(TAG, "failed to find contact for Mike Cleron");
+        } else {
+            Log.w(TAG, "Mike Cleron is " + personUri);
+        }
+        */
+
+        StringBuilder longSmsText = new StringBuilder();
+        int end = 2 + update;
+        if (end > LINES.length) {
+            end = LINES.length;
+        }
+        final int start = Math.max(0, end - MAX_LINES);
+        for (int i=start; i<end; i++) {
+            if (i >= LINES.length) break;
+            if (i > start) longSmsText.append("\n");
+            longSmsText.append(LINES[i]);
+        }
+        if (update > 2) {
+            when = System.currentTimeMillis();
+        }
+        Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle()
+                .bigText(longSmsText);
+        Notification bigText = new Notification.Builder(context)
+                .setContentTitle("Mike Cleron")
+                .setContentIntent(ToastService.getPendingIntent(context, "Clicked on bigText"))
+                .setContentText(longSmsText)
+                        //.setTicker("Mike Cleron: " + longSmsText)
+                .setWhen(when)
+                .setLargeIcon(getBitmap(context, R.drawable.bucket))
+                .setPriority(Notification.PRIORITY_HIGH)
+                .setNumber(update)
+                .setSmallIcon(R.drawable.stat_notify_talk_text)
+                .setStyle(bigTextStyle)
+                .setDefaults(Notification.DEFAULT_SOUND)
+                .addPerson(personUri)
+                .build();
+        return bigText;
+    }
+
+    public static Notification makeUploadNotification(Context context, int progress, long when) {
+        Notification.Builder uploadNotification = new Notification.Builder(context)
+                .setContentTitle("File Upload")
+                .setContentText("foo.txt")
+                .setPriority(Notification.PRIORITY_MIN)
+                .setContentIntent(ToastService.getPendingIntent(context, "Clicked on Upload"))
+                .setWhen(when)
+                .setSmallIcon(R.drawable.ic_menu_upload)
+                .setProgress(100, Math.min(progress, 100), false);
+        return uploadNotification.build();
+    }
+
+    static SpannableStringBuilder BOLD(CharSequence str) {
+        final SpannableStringBuilder ssb = new SpannableStringBuilder(str);
+        ssb.setSpan(new StyleSpan(Typeface.BOLD), 0, ssb.length(), 0);
+        return ssb;
+    }
+
+    public static class ToastService extends IntentService {
+
+        private static final String TAG = "ToastService";
+
+        private static final String ACTION_TOAST = "toast";
+
+        private Handler handler;
+
+        public ToastService() {
+            super(TAG);
+        }
+        public ToastService(String name) {
+            super(name);
+        }
+
+        @Override
+        public int onStartCommand(Intent intent, int flags, int startId) {
+            handler = new Handler();
+            return super.onStartCommand(intent, flags, startId);
+        }
+
+        @Override
+        protected void onHandleIntent(Intent intent) {
+            Log.v(TAG, "clicked a thing! intent=" + intent.toString());
+            if (intent.hasExtra("text")) {
+                final String text = intent.getStringExtra("text");
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Toast.makeText(ToastService.this, text, Toast.LENGTH_LONG).show();
+                        Log.v(TAG, "toast " + text);
+                    }
+                });
+            }
+        }
+
+        public static PendingIntent getPendingIntent(Context context, String text) {
+            Intent toastIntent = new Intent(context, ToastService.class);
+            toastIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            toastIntent.setAction(ACTION_TOAST + ":" + text); // one per toast message
+            toastIntent.putExtra("text", text);
+            PendingIntent pi = PendingIntent.getService(
+                    context, 58, toastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            return pi;
+        }
+    }
+
+    public static void sleepIfYouCan(int ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {}
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public static String summarize(Notification n) {
+        return String.format("<notif title=\"%s\" icon=0x%08x view=%s>",
+                n.extras.get(Notification.EXTRA_TITLE),
+                n.icon,
+                String.valueOf(n.contentView));
+    }
+    
+    public void testCreate() throws Exception {
+        ArrayList<Notification> mNotifications = new ArrayList<Notification>();
+        NotificationManager noMa =
+                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
+        L("Constructing notifications...");
+        if (SHOW_BIG_TEXT) {
+            int bigtextId = mNotifications.size();
+            final long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = makeBigTextNotification(mContext, 0, bigtextId, System.currentTimeMillis());
+            L("  %s: create=%dms", summarize(n), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(n);
+        }
+
+        int uploadId = mNotifications.size();
+        long uploadWhen = System.currentTimeMillis();
+
+        if (SHOW_PROGRESS) {
+            mNotifications.add(makeUploadNotification(mContext, 0, uploadWhen));
+        }
+
+        if (SHOW_PHONE_CALL) {
+            int phoneId = mNotifications.size();
+            final PendingIntent fullscreenIntent
+                    = FullScreenActivity.getPendingIntent(mContext, phoneId);
+            final long time = SystemClock.currentThreadTimeMillis();
+            Notification phoneCall = new Notification.Builder(mContext)
+                    .setContentTitle("Incoming call")
+                    .setContentText("Matias Duarte")
+                    .setLargeIcon(getBitmap(mContext, R.drawable.matias_hed))
+                    .setSmallIcon(R.drawable.stat_sys_phone_call)
+                    .setDefaults(Notification.DEFAULT_SOUND)
+                    .setPriority(Notification.PRIORITY_MAX)
+                    .setContentIntent(fullscreenIntent)
+                    .setFullScreenIntent(fullscreenIntent, true)
+                    .addAction(R.drawable.ic_dial_action_call, "Answer",
+                            ToastService.getPendingIntent(mContext, "Clicked on Answer"))
+                    .addAction(R.drawable.ic_end_call, "Ignore",
+                            ToastService.getPendingIntent(mContext, "Clicked on Ignore"))
+                    .setOngoing(true)
+                    .addPerson(Uri.fromParts("tel", "1 (617) 555-1212", null).toString())
+                    .build();
+            L("  %s: create=%dms", phoneCall.toString(), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(phoneCall);
+        }
+
+        if (SHOW_STOPWATCH) {
+            final long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = new Notification.Builder(mContext)
+                    .setContentTitle("Stopwatch PRO")
+                    .setContentText("Counting up")
+                    .setContentIntent(ToastService.getPendingIntent(mContext, "Clicked on Stopwatch"))
+                    .setSmallIcon(R.drawable.stat_notify_alarm)
+                    .setUsesChronometer(true)
+                    .build();
+            L("  %s: create=%dms", summarize(n), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(n);
+        }
+
+        if (SHOW_CALENDAR) {
+            final long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = new Notification.Builder(mContext)
+                    .setContentTitle("J Planning")
+                    .setContentText("The Botcave")
+                    .setWhen(System.currentTimeMillis())
+                    .setSmallIcon(R.drawable.stat_notify_calendar)
+                    .setContentIntent(ToastService.getPendingIntent(mContext, "Clicked on calendar event"))
+                    .setContentInfo("7PM")
+                    .addAction(R.drawable.stat_notify_snooze, "+10 min",
+                            ToastService.getPendingIntent(mContext, "snoozed 10 min"))
+                    .addAction(R.drawable.stat_notify_snooze_longer, "+1 hour",
+                            ToastService.getPendingIntent(mContext, "snoozed 1 hr"))
+                    .addAction(R.drawable.stat_notify_email, "Email",
+                            ToastService.getPendingIntent(mContext,
+                                    "Congratulations, you just destroyed someone's inbox zero"))
+                    .build();
+            L("  %s: create=%dms", summarize(n), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(n);
+        }
+
+        if (SHOW_BIG_PICTURE) {
+            BitmapDrawable d =
+                    (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.romainguy_rockaway);
+            final long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = new Notification.Builder(mContext)
+                        .setContentTitle("Romain Guy")
+                        .setContentText("I was lucky to find a Canon 5D Mk III at a local Bay Area "
+                                + "store last week but I had not been able to try it in the field "
+                                + "until tonight. After a few days of rain the sky finally cleared "
+                                + "up. Rockaway Beach did not disappoint and I was finally able to "
+                                + "see what my new camera feels like when shooting landscapes.")
+                        .setSmallIcon(android.R.drawable.stat_notify_chat)
+                        .setContentIntent(
+                                ToastService.getPendingIntent(mContext, "Clicked picture"))
+                        .setLargeIcon(getBitmap(mContext, R.drawable.romainguy_hed))
+                        .addAction(R.drawable.add, "Add to Gallery",
+                                ToastService.getPendingIntent(mContext, "Added"))
+                        .setStyle(new Notification.BigPictureStyle()
+                                .bigPicture(d.getBitmap()))
+                        .build();
+            L("  %s: create=%dms", summarize(n), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(n);
+        }
+
+        if (SHOW_INBOX) {
+            final long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = new Notification.Builder(mContext)
+                    .setContentTitle("New mail")
+                    .setContentText("3 new messages")
+                    .setSubText("example@gmail.com")
+                    .setContentIntent(ToastService.getPendingIntent(mContext, "Clicked on Mail"))
+                    .setSmallIcon(R.drawable.stat_notify_email)
+                    .setStyle(new Notification.InboxStyle()
+                                    .setSummaryText("example@gmail.com")
+                                    .addLine(BOLD("Alice:").append(" hey there!"))
+                                    .addLine(BOLD("Bob:").append(" hi there!"))
+                                    .addLine(BOLD("Charlie:").append(" Iz IN UR EMAILZ!!"))
+                    ).build();
+            L("  %s: create=%dms", summarize(n), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(n);
+        }
+
+        if (SHOW_SOCIAL) {
+            final long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = new Notification.Builder(mContext)
+                    .setContentTitle("Social Network")
+                    .setContentText("You were mentioned in a post")
+                    .setContentInfo("example@gmail.com")
+                    .setContentIntent(ToastService.getPendingIntent(mContext, "Clicked on Social"))
+                    .setSmallIcon(android.R.drawable.stat_notify_chat)
+                    .setPriority(Notification.PRIORITY_LOW)
+                    .build();
+            L("  %s: create=%dms", summarize(n), SystemClock.currentThreadTimeMillis() - time);
+            mNotifications.add(n);
+        }
+
+        L("Posting notifications...");
+        for (int i=0; i<mNotifications.size(); i++) {
+            final int count = 4;
+            for (int j=0; j<count; j++) {
+                long time = SystemClock.currentThreadTimeMillis();
+                final Notification n = mNotifications.get(i);
+                noMa.notify(NOTIFICATION_ID + i, n);
+                time = SystemClock.currentThreadTimeMillis() - time;
+                L("  %s: notify=%dms (%d/%d)", summarize(n), time,
+                        j + 1, count);
+                sleepIfYouCan(150);
+            }
+        }
+
+        sleepIfYouCan(1000);
+
+        L("Canceling notifications...");
+        for (int i=0; i<mNotifications.size(); i++) {
+            final Notification n = mNotifications.get(i);
+            long time = SystemClock.currentThreadTimeMillis();
+            noMa.cancel(NOTIFICATION_ID + i);
+            time = SystemClock.currentThreadTimeMillis() - time;
+            L("  %s: cancel=%dms", summarize(n), time);
+        }
+
+        sleepIfYouCan(500);
+
+        L("Parceling notifications...");
+        // we want to be able to use this test on older OSes that do not have getBlobAshmemSize
+        Method getBlobAshmemSize = null;
+        try {
+            getBlobAshmemSize = Parcel.class.getMethod("getBlobAshmemSize");
+        } catch (NoSuchMethodException ex) {
+        }
+        for (int i=0; i<mNotifications.size(); i++) {
+            Parcel p = Parcel.obtain();
+            {
+                final Notification n = mNotifications.get(i);
+                long time = SystemClock.currentThreadTimeMillis();
+                n.writeToParcel(p, 0);
+                time = SystemClock.currentThreadTimeMillis() - time;
+                L("  %s: write parcel=%dms size=%d ashmem=%s",
+                        summarize(n), time, p.dataPosition(),
+                        (getBlobAshmemSize != null)
+                            ? getBlobAshmemSize.invoke(p)
+                            : "???");
+                p.setDataPosition(0);
+            }
+
+            long time = SystemClock.currentThreadTimeMillis();
+            final Notification n2 = Notification.CREATOR.createFromParcel(p);
+            time = SystemClock.currentThreadTimeMillis() - time;
+            L("  %s: parcel read=%dms", summarize(n2), time);
+
+            time = SystemClock.currentThreadTimeMillis();
+            noMa.notify(NOTIFICATION_ID + i, n2);
+            time = SystemClock.currentThreadTimeMillis() - time;
+            L("  %s: notify=%dms", summarize(n2), time);
+        }
+
+        sleepIfYouCan(500);
+
+        L("Canceling notifications...");
+        for (int i=0; i<mNotifications.size(); i++) {
+            long time = SystemClock.currentThreadTimeMillis();
+            final Notification n = mNotifications.get(i);
+            noMa.cancel(NOTIFICATION_ID + i);
+            time = SystemClock.currentThreadTimeMillis() - time;
+            L("  %s: cancel=%dms", summarize(n), time);
+        }
+
+
+//            if (SHOW_PROGRESS) {
+//                ProgressService.startProgressUpdater(this, uploadId, uploadWhen, 0);
+//            }
+    }
+
+    public static class FullScreenActivity extends Activity {
+        public static final String EXTRA_ID = "id";
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.full_screen);
+            final Intent intent = getIntent();
+            if (intent != null && intent.hasExtra(EXTRA_ID)) {
+                final int id = intent.getIntExtra(EXTRA_ID, -1);
+                if (id >= 0) {
+                    NotificationManager noMa =
+                            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+                    noMa.cancel(NOTIFICATION_ID + id);
+                }
+            }
+        }
+
+        public void dismiss(View v) {
+            finish();
+        }
+
+        public static PendingIntent getPendingIntent(Context context, int id) {
+            Intent fullScreenIntent = new Intent(context, FullScreenActivity.class);
+            fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            fullScreenIntent.putExtra(EXTRA_ID, id);
+            PendingIntent pi = PendingIntent.getActivity(
+                    context, 22, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            return pi;
+        }
+    }
+}
+