Merge "AudioManager: add previous AudioPort list" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 7df09a1..6e520b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -217,6 +217,7 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int __reserved0 = 16844020; // 0x10104f4
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -300,7 +301,6 @@
     field public static final int anyDensity = 16843372; // 0x101026c
     field public static final int apduServiceBanner = 16843757; // 0x10103ed
     field public static final int apiKey = 16843281; // 0x1010211
-    field public static final int assistBlocked = 16844020; // 0x10104f4
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -5835,7 +5835,6 @@
     field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
     field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
     field public static final java.lang.String ACTION_SYSTEM_UPDATE_POLICY_CHANGED = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";
-    field public static final int DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
     field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
@@ -5900,6 +5899,7 @@
     field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
     field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
     field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
+    field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -9341,6 +9341,7 @@
     field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
     field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
     field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
+    field public static final java.lang.String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
     field public static final java.lang.String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
     field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
     field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
@@ -22667,6 +22668,7 @@
     ctor public Build.VERSION();
     field public static final java.lang.String CODENAME;
     field public static final java.lang.String INCREMENTAL;
+    field public static final int PREVIEW_SDK_INT;
     field public static final java.lang.String RELEASE;
     field public static final deprecated java.lang.String SDK;
     field public static final int SDK_INT;
@@ -28506,6 +28508,53 @@
   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
@@ -28525,6 +28574,14 @@
   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 {
+  }
+
   public class KeyStoreKeySpec implements java.security.spec.KeySpec {
     method public java.lang.String[] getBlockModes();
     method public java.lang.String[] getDigests();
@@ -28538,9 +28595,9 @@
     method public int getPurposes();
     method public java.lang.String[] getSignaturePaddings();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public boolean isTeeBacked();
+    method public boolean isInsideSecureHardware();
     method public boolean isUserAuthenticationRequired();
-    method public boolean isUserAuthenticationRequirementTeeEnforced();
+    method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
   }
 
   public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
@@ -30108,6 +30165,8 @@
     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();
+    method public int getVideoState();
     method public void onAudioStateChanged(android.telecom.AudioState);
     method public void onConnectionAdded(android.telecom.Connection);
     method public void onDisconnect();
@@ -30127,6 +30186,8 @@
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setOnHold();
     method public final void setStatusHints(android.telecom.StatusHints);
+    method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
+    method public final void setVideoState(android.telecom.Connection, int);
     field public static final long CONNECT_TIME_NOT_SPECIFIED = 0L; // 0x0L
   }
 
@@ -30154,6 +30215,7 @@
     method public final android.telecom.Connection.VideoProvider getVideoProvider();
     method public final boolean isRingbackRequested();
     method public void onAbort();
+    method public void onAnswer(int);
     method public void onAnswer();
     method public void onAudioStateChanged(android.telecom.AudioState);
     method public void onDisconnect();
@@ -30183,7 +30245,11 @@
     method public final void setRingbackRequested(boolean);
     method public final void setRinging();
     method public final void setStatusHints(android.telecom.StatusHints);
+    method public final void setVideoProvider(android.telecom.Connection.VideoProvider);
+    method public final void setVideoState(int);
     method public static java.lang.String stateToString(int);
+    field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -30191,6 +30257,12 @@
     field public static final int CAPABILITY_MUTE = 64; // 0x40
     field public static final int CAPABILITY_RESPOND_VIA_TEXT = 32; // 0x20
     field public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 4096; // 0x1000
+    field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 768; // 0x300
+    field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 256; // 0x100
+    field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 512; // 0x200
+    field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 3072; // 0xc00
+    field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 1024; // 0x400
+    field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
     field public static final int STATE_ACTIVE = 4; // 0x4
@@ -30236,10 +30308,12 @@
 
   public final class ConnectionRequest implements android.os.Parcelable {
     ctor public ConnectionRequest(android.telecom.PhoneAccountHandle, android.net.Uri, android.os.Bundle);
+    ctor public ConnectionRequest(android.telecom.PhoneAccountHandle, android.net.Uri, android.os.Bundle, int);
     method public int describeContents();
     method public android.telecom.PhoneAccountHandle getAccountHandle();
     method public android.net.Uri getAddress();
     method public android.os.Bundle getExtras();
+    method public int getVideoState();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telecom.ConnectionRequest> CREATOR;
   }
@@ -35828,7 +35902,7 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public void dispatchProvideAssistStructure(android.view.ViewAssistStructure);
+    method public void dispatchProvideStructure(android.view.ViewStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -36008,7 +36082,6 @@
     method public void invalidateOutline();
     method public boolean isAccessibilityFocused();
     method public boolean isActivated();
-    method public boolean isAssistBlocked();
     method public boolean isAttachedToWindow();
     method public boolean isClickable();
     method public boolean isDirty();
@@ -36090,8 +36163,8 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public void onProvideAssistStructure(android.view.ViewAssistStructure);
-    method public void onProvideVirtualAssistStructure(android.view.ViewAssistStructure);
+    method public void onProvideStructure(android.view.ViewStructure);
+    method public void onProvideVirtualStructure(android.view.ViewStructure);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -36154,7 +36227,6 @@
     method public void setActivated(boolean);
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
-    method public void setAssistBlocked(boolean);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
     method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -36517,40 +36589,8 @@
     method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
-  public abstract class ViewAssistStructure {
+  public abstract deprecated class ViewAssistStructure extends android.view.ViewStructure {
     ctor public ViewAssistStructure();
-    method public abstract void asyncCommit();
-    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
-    method public abstract void clearExtras();
-    method public abstract android.os.Bundle editExtras();
-    method public abstract int getChildCount();
-    method public abstract java.lang.CharSequence getHint();
-    method public abstract java.lang.CharSequence getText();
-    method public abstract int getTextSelectionEnd();
-    method public abstract int getTextSelectionStart();
-    method public abstract android.view.ViewAssistStructure newChild(int);
-    method public abstract void setAccessibilityFocused(boolean);
-    method public abstract void setActivated(boolean);
-    method public abstract void setAssistBlocked(boolean);
-    method public abstract void setCheckable(boolean);
-    method public abstract void setChecked(boolean);
-    method public abstract void setChildCount(int);
-    method public abstract void setClassName(java.lang.String);
-    method public abstract void setClickable(boolean);
-    method public abstract void setContentDescription(java.lang.CharSequence);
-    method public abstract void setDimens(int, int, int, int, int, int);
-    method public abstract void setEnabled(boolean);
-    method public abstract void setFocusable(boolean);
-    method public abstract void setFocused(boolean);
-    method public abstract void setHint(java.lang.CharSequence);
-    method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
-    method public abstract void setLongClickable(boolean);
-    method public abstract void setSelected(boolean);
-    method public abstract void setStylusButtonPressable(boolean);
-    method public abstract void setText(java.lang.CharSequence);
-    method public abstract void setText(java.lang.CharSequence, int, int);
-    method public abstract void setTextPaint(android.text.TextPaint);
-    method public abstract void setVisibility(int);
   }
 
   public class ViewConfiguration {
@@ -36927,6 +36967,41 @@
     method public android.view.ViewPropertyAnimator zBy(float);
   }
 
+  public abstract class ViewStructure {
+    ctor public ViewStructure();
+    method public abstract void asyncCommit();
+    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
+    method public abstract int getChildCount();
+    method public abstract android.os.Bundle getExtras();
+    method public abstract java.lang.CharSequence getHint();
+    method public abstract java.lang.CharSequence getText();
+    method public abstract int getTextSelectionEnd();
+    method public abstract int getTextSelectionStart();
+    method public abstract boolean hasExtras();
+    method public abstract android.view.ViewAssistStructure newChild(int);
+    method public abstract void setAccessibilityFocused(boolean);
+    method public abstract void setActivated(boolean);
+    method public abstract void setCheckable(boolean);
+    method public abstract void setChecked(boolean);
+    method public abstract void setChildCount(int);
+    method public abstract void setClassName(java.lang.String);
+    method public abstract void setClickable(boolean);
+    method public abstract void setContentDescription(java.lang.CharSequence);
+    method public abstract void setDimens(int, int, int, int, int, int);
+    method public abstract void setEnabled(boolean);
+    method public abstract void setFocusable(boolean);
+    method public abstract void setFocused(boolean);
+    method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setLongClickable(boolean);
+    method public abstract void setSelected(boolean);
+    method public abstract void setStylusButtonPressable(boolean);
+    method public abstract void setText(java.lang.CharSequence);
+    method public abstract void setText(java.lang.CharSequence, int, int);
+    method public abstract void setTextPaint(android.text.TextPaint);
+    method public abstract void setVisibility(int);
+  }
+
   public final class ViewStub extends android.view.View {
     ctor public ViewStub(android.content.Context);
     ctor public ViewStub(android.content.Context, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 0662d93..7445805 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -289,6 +289,7 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int __reserved0 = 16844020; // 0x10104f4
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -372,7 +373,6 @@
     field public static final int anyDensity = 16843372; // 0x101026c
     field public static final int apduServiceBanner = 16843757; // 0x10103ed
     field public static final int apiKey = 16843281; // 0x1010211
-    field public static final int assistBlocked = 16844020; // 0x10104f4
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -5943,7 +5943,6 @@
     field public static final java.lang.String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER";
     field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
     field public static final java.lang.String ACTION_SYSTEM_UPDATE_POLICY_CHANGED = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";
-    field public static final int DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
     field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
@@ -6011,6 +6010,7 @@
     field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
     field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
     field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
+    field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -9600,6 +9600,7 @@
     field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
     field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
     field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
+    field public static final java.lang.String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
     field public static final java.lang.String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
     field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
     field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
@@ -24566,6 +24567,7 @@
     ctor public Build.VERSION();
     field public static final java.lang.String CODENAME;
     field public static final java.lang.String INCREMENTAL;
+    field public static final int PREVIEW_SDK_INT;
     field public static final java.lang.String RELEASE;
     field public static final deprecated java.lang.String SDK;
     field public static final int SDK_INT;
@@ -30520,6 +30522,53 @@
   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
@@ -30539,6 +30588,14 @@
   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 {
+  }
+
   public class KeyStoreKeySpec implements java.security.spec.KeySpec {
     method public java.lang.String[] getBlockModes();
     method public java.lang.String[] getDigests();
@@ -30552,9 +30609,9 @@
     method public int getPurposes();
     method public java.lang.String[] getSignaturePaddings();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public boolean isTeeBacked();
+    method public boolean isInsideSecureHardware();
     method public boolean isUserAuthenticationRequired();
-    method public boolean isUserAuthenticationRequirementTeeEnforced();
+    method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
   }
 
   public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
@@ -32229,6 +32286,8 @@
     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();
+    method public int getVideoState();
     method public void onAudioStateChanged(android.telecom.AudioState);
     method public void onConnectionAdded(android.telecom.Connection);
     method public void onDisconnect();
@@ -32248,6 +32307,8 @@
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setOnHold();
     method public final void setStatusHints(android.telecom.StatusHints);
+    method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
+    method public final void setVideoState(android.telecom.Connection, int);
     field public static final long CONNECT_TIME_NOT_SPECIFIED = 0L; // 0x0L
   }
 
@@ -32275,6 +32336,7 @@
     method public final android.telecom.Connection.VideoProvider getVideoProvider();
     method public final boolean isRingbackRequested();
     method public void onAbort();
+    method public void onAnswer(int);
     method public void onAnswer();
     method public void onAudioStateChanged(android.telecom.AudioState);
     method public void onDisconnect();
@@ -32304,7 +32366,11 @@
     method public final void setRingbackRequested(boolean);
     method public final void setRinging();
     method public final void setStatusHints(android.telecom.StatusHints);
+    method public final void setVideoProvider(android.telecom.Connection.VideoProvider);
+    method public final void setVideoState(int);
     method public static java.lang.String stateToString(int);
+    field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -32312,6 +32378,12 @@
     field public static final int CAPABILITY_MUTE = 64; // 0x40
     field public static final int CAPABILITY_RESPOND_VIA_TEXT = 32; // 0x20
     field public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 4096; // 0x1000
+    field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 768; // 0x300
+    field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 256; // 0x100
+    field public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 512; // 0x200
+    field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 3072; // 0xc00
+    field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 1024; // 0x400
+    field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
     field public static final int STATE_ACTIVE = 4; // 0x4
@@ -32357,10 +32429,12 @@
 
   public final class ConnectionRequest implements android.os.Parcelable {
     ctor public ConnectionRequest(android.telecom.PhoneAccountHandle, android.net.Uri, android.os.Bundle);
+    ctor public ConnectionRequest(android.telecom.PhoneAccountHandle, android.net.Uri, android.os.Bundle, int);
     method public int describeContents();
     method public android.telecom.PhoneAccountHandle getAccountHandle();
     method public android.net.Uri getAddress();
     method public android.os.Bundle getExtras();
+    method public int getVideoState();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telecom.ConnectionRequest> CREATOR;
   }
@@ -38039,7 +38113,7 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public void dispatchProvideAssistStructure(android.view.ViewAssistStructure);
+    method public void dispatchProvideStructure(android.view.ViewStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -38219,7 +38293,6 @@
     method public void invalidateOutline();
     method public boolean isAccessibilityFocused();
     method public boolean isActivated();
-    method public boolean isAssistBlocked();
     method public boolean isAttachedToWindow();
     method public boolean isClickable();
     method public boolean isDirty();
@@ -38301,8 +38374,8 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public void onProvideAssistStructure(android.view.ViewAssistStructure);
-    method public void onProvideVirtualAssistStructure(android.view.ViewAssistStructure);
+    method public void onProvideStructure(android.view.ViewStructure);
+    method public void onProvideVirtualStructure(android.view.ViewStructure);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -38365,7 +38438,6 @@
     method public void setActivated(boolean);
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
-    method public void setAssistBlocked(boolean);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
     method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -38728,40 +38800,8 @@
     method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
-  public abstract class ViewAssistStructure {
+  public abstract deprecated class ViewAssistStructure extends android.view.ViewStructure {
     ctor public ViewAssistStructure();
-    method public abstract void asyncCommit();
-    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
-    method public abstract void clearExtras();
-    method public abstract android.os.Bundle editExtras();
-    method public abstract int getChildCount();
-    method public abstract java.lang.CharSequence getHint();
-    method public abstract java.lang.CharSequence getText();
-    method public abstract int getTextSelectionEnd();
-    method public abstract int getTextSelectionStart();
-    method public abstract android.view.ViewAssistStructure newChild(int);
-    method public abstract void setAccessibilityFocused(boolean);
-    method public abstract void setActivated(boolean);
-    method public abstract void setAssistBlocked(boolean);
-    method public abstract void setCheckable(boolean);
-    method public abstract void setChecked(boolean);
-    method public abstract void setChildCount(int);
-    method public abstract void setClassName(java.lang.String);
-    method public abstract void setClickable(boolean);
-    method public abstract void setContentDescription(java.lang.CharSequence);
-    method public abstract void setDimens(int, int, int, int, int, int);
-    method public abstract void setEnabled(boolean);
-    method public abstract void setFocusable(boolean);
-    method public abstract void setFocused(boolean);
-    method public abstract void setHint(java.lang.CharSequence);
-    method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
-    method public abstract void setLongClickable(boolean);
-    method public abstract void setSelected(boolean);
-    method public abstract void setStylusButtonPressable(boolean);
-    method public abstract void setText(java.lang.CharSequence);
-    method public abstract void setText(java.lang.CharSequence, int, int);
-    method public abstract void setTextPaint(android.text.TextPaint);
-    method public abstract void setVisibility(int);
   }
 
   public class ViewConfiguration {
@@ -39138,6 +39178,41 @@
     method public android.view.ViewPropertyAnimator zBy(float);
   }
 
+  public abstract class ViewStructure {
+    ctor public ViewStructure();
+    method public abstract void asyncCommit();
+    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
+    method public abstract int getChildCount();
+    method public abstract android.os.Bundle getExtras();
+    method public abstract java.lang.CharSequence getHint();
+    method public abstract java.lang.CharSequence getText();
+    method public abstract int getTextSelectionEnd();
+    method public abstract int getTextSelectionStart();
+    method public abstract boolean hasExtras();
+    method public abstract android.view.ViewAssistStructure newChild(int);
+    method public abstract void setAccessibilityFocused(boolean);
+    method public abstract void setActivated(boolean);
+    method public abstract void setCheckable(boolean);
+    method public abstract void setChecked(boolean);
+    method public abstract void setChildCount(int);
+    method public abstract void setClassName(java.lang.String);
+    method public abstract void setClickable(boolean);
+    method public abstract void setContentDescription(java.lang.CharSequence);
+    method public abstract void setDimens(int, int, int, int, int, int);
+    method public abstract void setEnabled(boolean);
+    method public abstract void setFocusable(boolean);
+    method public abstract void setFocused(boolean);
+    method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setLongClickable(boolean);
+    method public abstract void setSelected(boolean);
+    method public abstract void setStylusButtonPressable(boolean);
+    method public abstract void setText(java.lang.CharSequence);
+    method public abstract void setText(java.lang.CharSequence, int, int);
+    method public abstract void setTextPaint(android.text.TextPaint);
+    method public abstract void setVisibility(int);
+  }
+
   public final class ViewStub extends android.view.View {
     ctor public ViewStub(android.content.Context);
     ctor public ViewStub(android.content.Context, int);
@@ -41728,7 +41803,7 @@
     method public abstract boolean onKeyUp(int, android.view.KeyEvent);
     method public abstract void onMeasure(int, int);
     method public abstract void onOverScrolled(int, int, boolean, boolean);
-    method public abstract void onProvideVirtualAssistStructure(android.view.ViewAssistStructure);
+    method public abstract void onProvideVirtualAssistStructure(android.view.ViewStructure);
     method public abstract void onScrollChanged(int, int, int, int);
     method public abstract void onSizeChanged(int, int, int, int);
     method public abstract void onStartTemporaryDetach();
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index bb25ec6..21dc1e2 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -630,7 +630,10 @@
                     }
                     glDisable(GL_SCISSOR_TEST);
                 }
-                glDrawTexiOES(xc, yc, 0, animation.width, animation.height);
+                // specify the y center as ceiling((mHeight - animation.height) / 2)
+                // which is equivalent to mHeight - (yc + animation.height)
+                glDrawTexiOES(xc, mHeight - (yc + animation.height),
+                              0, animation.width, animation.height);
                 eglSwapBuffers(mDisplay, mSurface);
 
                 nsecs_t now = systemTime();
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 427ecce..435d5ab 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -108,7 +108,7 @@
             float pathErrorScale) throws NotFoundException {
         final ConfigurationBoundResourceCache<Animator> animatorCache = resources
                 .getAnimatorCache();
-        Animator animator = animatorCache.get(id, theme);
+        Animator animator = animatorCache.getInstance(id, theme);
         if (animator != null) {
             if (DBG_ANIMATOR_INFLATER) {
                 Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
@@ -157,7 +157,7 @@
         final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
                 .getStateListAnimatorCache();
         final Theme theme = context.getTheme();
-        StateListAnimator animator = cache.get(id, theme);
+        StateListAnimator animator = cache.getInstance(id, theme);
         if (animator != null) {
             return animator;
         }
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 5790682..cdd72be 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -28,6 +28,7 @@
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * This class enables automatic animations on layout changes in ViewGroup objects. To enable
@@ -757,7 +758,7 @@
         // reset the inter-animation delay, in case we use it later
         staggerDelay = 0;
 
-        final ViewTreeObserver observer = parent.getViewTreeObserver(); // used for later cleanup
+        final ViewTreeObserver observer = parent.getViewTreeObserver();
         if (!observer.isAlive()) {
             // If the observer's not in a good state, skip the transition
             return;
@@ -790,21 +791,9 @@
         // This is the cleanup step. When we get this rendering event, we know that all of
         // the appropriate animations have been set up and run. Now we can clear out the
         // layout listeners.
-        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-            public boolean onPreDraw() {
-                parent.getViewTreeObserver().removeOnPreDrawListener(this);
-                int count = layoutChangeListenerMap.size();
-                if (count > 0) {
-                    Collection<View> views = layoutChangeListenerMap.keySet();
-                    for (View view : views) {
-                        View.OnLayoutChangeListener listener = layoutChangeListenerMap.get(view);
-                        view.removeOnLayoutChangeListener(listener);
-                    }
-                }
-                layoutChangeListenerMap.clear();
-                return true;
-            }
-        });
+        CleanupCallback callback = new CleanupCallback(layoutChangeListenerMap, parent);
+        observer.addOnPreDrawListener(callback);
+        parent.addOnAttachStateChangeListener(callback);
     }
 
     /**
@@ -1499,4 +1488,50 @@
                 View view, int transitionType);
     }
 
+    /**
+     * Utility class to clean up listeners after animations are setup. Cleanup happens
+     * when either the OnPreDrawListener method is called or when the parent is detached,
+     * whichever comes first.
+     */
+    private static final class CleanupCallback implements ViewTreeObserver.OnPreDrawListener,
+            View.OnAttachStateChangeListener {
+
+        final Map<View, View.OnLayoutChangeListener> layoutChangeListenerMap;
+        final ViewGroup parent;
+
+        CleanupCallback(Map<View, View.OnLayoutChangeListener> listenerMap, ViewGroup parent) {
+            this.layoutChangeListenerMap = listenerMap;
+            this.parent = parent;
+        }
+
+        private void cleanup() {
+            parent.getViewTreeObserver().removeOnPreDrawListener(this);
+            parent.removeOnAttachStateChangeListener(this);
+            int count = layoutChangeListenerMap.size();
+            if (count > 0) {
+                Collection<View> views = layoutChangeListenerMap.keySet();
+                for (View view : views) {
+                    View.OnLayoutChangeListener listener = layoutChangeListenerMap.get(view);
+                    view.removeOnLayoutChangeListener(listener);
+                }
+                layoutChangeListenerMap.clear();
+            }
+        }
+
+        @Override
+        public void onViewAttachedToWindow(View v) {
+        }
+
+        @Override
+        public void onViewDetachedFromWindow(View v) {
+            cleanup();
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            cleanup();
+            return true;
+        }
+    };
+
 }
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 94e3b66..4d34349 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -33,6 +33,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.Window;
 import android.widget.SpinnerAdapter;
 import java.lang.annotation.Retention;
@@ -1373,5 +1374,13 @@
          * version of the SDK an app can end up statically linking to the new MarginLayoutParams
          * overload, causing a crash when running on older platform versions with no other changes.
          */
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+
+            encoder.addProperty("gravity", gravity);
+        }
     }
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index da6d8c5..f506d59 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -38,6 +38,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.Resources.Theme;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDebug;
 import android.database.sqlite.SQLiteDebug.DbStats;
@@ -570,8 +571,6 @@
     private native void dumpGraphicsInfo(FileDescriptor fd);
 
     private class ApplicationThread extends ApplicationThreadNative {
-        private static final String ONE_COUNT_COLUMN = "%21s %8d";
-        private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
         private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
 
         private int mLastProcessState = -1;
@@ -971,18 +970,18 @@
 
         @Override
         public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik, String[] args) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) {
             FileOutputStream fout = new FileOutputStream(fd);
             PrintWriter pw = new FastPrintWriter(fout);
             try {
-                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik);
+                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly);
             } finally {
                 pw.flush();
             }
         }
 
         private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -1006,7 +1005,8 @@
             long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class);
             SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
 
-            dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, Process.myPid(),
+            dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
+                    Process.myPid(),
                     (mBoundApplication != null) ? mBoundApplication.processName : "unknown",
                     nativeMax, nativeAllocated, nativeFree,
                     dalvikMax, dalvikAllocated, dalvikFree);
@@ -1934,6 +1934,9 @@
             = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
     private static final String HEAP_COLUMN
             = "%13s %8s %8s %8s %8s %8s %8s %8s";
+    private static final String ONE_COUNT_COLUMN = "%21s %8d";
+    private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
+    private static final String ONE_COUNT_COLUMN_HEADER = "%21s %8s";
 
     // Formatting for checkin service - update version if row format changes
     private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 3;
@@ -1943,7 +1946,8 @@
     }
 
     public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
-            boolean dumpFullInfo, boolean dumpDalvik, int pid, String processName,
+            boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+            int pid, String processName,
             long nativeMax, long nativeAllocated, long nativeFree,
             long dalvikMax, long dalvikAllocated, long dalvikFree) {
 
@@ -2024,106 +2028,50 @@
             return;
         }
 
-        // otherwise, show human-readable format
-        if (dumpFullInfo) {
-            printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
-                    "Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
-            printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
-                    "Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
-            printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
-                    "------", "------", "------", "------", "------", "------");
-            printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
-                    memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
-                    memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
-                    memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
-                    nativeMax, nativeAllocated, nativeFree);
-            printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
-                    memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
-                    memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
-                    memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
-                    dalvikMax, dalvikAllocated, dalvikFree);
-        } else {
-            printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
-                    "Private", "Swapped", "Heap", "Heap", "Heap");
-            printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
-                    "Clean", "Dirty", "Size", "Alloc", "Free");
-            printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
-                    "------", "------", "------", "------", "------");
-            printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
-                    memInfo.nativePrivateDirty,
-                    memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
-                    nativeMax, nativeAllocated, nativeFree);
-            printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
-                    memInfo.dalvikPrivateDirty,
-                    memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
-                    dalvikMax, dalvikAllocated, dalvikFree);
-        }
-
-        int otherPss = memInfo.otherPss;
-        int otherSwappablePss = memInfo.otherSwappablePss;
-        int otherSharedDirty = memInfo.otherSharedDirty;
-        int otherPrivateDirty = memInfo.otherPrivateDirty;
-        int otherSharedClean = memInfo.otherSharedClean;
-        int otherPrivateClean = memInfo.otherPrivateClean;
-        int otherSwappedOut = memInfo.otherSwappedOut;
-
-        for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
-            final int myPss = memInfo.getOtherPss(i);
-            final int mySwappablePss = memInfo.getOtherSwappablePss(i);
-            final int mySharedDirty = memInfo.getOtherSharedDirty(i);
-            final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
-            final int mySharedClean = memInfo.getOtherSharedClean(i);
-            final int myPrivateClean = memInfo.getOtherPrivateClean(i);
-            final int mySwappedOut = memInfo.getOtherSwappedOut(i);
-            if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
-                    || mySharedClean != 0 || myPrivateClean != 0 || mySwappedOut != 0) {
-                if (dumpFullInfo) {
-                    printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
-                            myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
-                            mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
-                } else {
-                    printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
-                            myPss, myPrivateDirty,
-                            myPrivateClean, mySwappedOut, "", "", "");
-                }
-                otherPss -= myPss;
-                otherSwappablePss -= mySwappablePss;
-                otherSharedDirty -= mySharedDirty;
-                otherPrivateDirty -= myPrivateDirty;
-                otherSharedClean -= mySharedClean;
-                otherPrivateClean -= myPrivateClean;
-                otherSwappedOut -= mySwappedOut;
+        if (!dumpSummaryOnly) {
+            if (dumpFullInfo) {
+                printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
+                        "Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
+                printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
+                        "Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
+                printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
+                        "------", "------", "------", "------", "------", "------");
+                printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
+                        memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
+                        memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
+                        memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
+                        nativeMax, nativeAllocated, nativeFree);
+                printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
+                        memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
+                        memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
+                        memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
+                        dalvikMax, dalvikAllocated, dalvikFree);
+            } else {
+                printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
+                        "Private", "Swapped", "Heap", "Heap", "Heap");
+                printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
+                        "Clean", "Dirty", "Size", "Alloc", "Free");
+                printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
+                        "------", "------", "------", "------", "------");
+                printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
+                        memInfo.nativePrivateDirty,
+                        memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
+                        nativeMax, nativeAllocated, nativeFree);
+                printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
+                        memInfo.dalvikPrivateDirty,
+                        memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
+                        dalvikMax, dalvikAllocated, dalvikFree);
             }
-        }
 
-        if (dumpFullInfo) {
-            printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
-                    otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
-                    otherSwappedOut, "", "", "");
-            printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
-                    memInfo.getTotalSwappablePss(),
-                    memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
-                    memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
-                    memInfo.getTotalSwappedOut(), nativeMax+dalvikMax,
-                    nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
-        } else {
-            printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
-                    otherPrivateDirty, otherPrivateClean, otherSwappedOut,
-                    "", "", "");
-            printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
-                    memInfo.getTotalPrivateDirty(),
-                    memInfo.getTotalPrivateClean(),
-                    memInfo.getTotalSwappedOut(),
-                    nativeMax+dalvikMax,
-                    nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
-        }
+            int otherPss = memInfo.otherPss;
+            int otherSwappablePss = memInfo.otherSwappablePss;
+            int otherSharedDirty = memInfo.otherSharedDirty;
+            int otherPrivateDirty = memInfo.otherPrivateDirty;
+            int otherSharedClean = memInfo.otherSharedClean;
+            int otherPrivateClean = memInfo.otherPrivateClean;
+            int otherSwappedOut = memInfo.otherSwappedOut;
 
-        if (dumpDalvik) {
-            pw.println(" ");
-            pw.println(" Dalvik Details");
-
-            for (int i=Debug.MemoryInfo.NUM_OTHER_STATS;
-                 i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) {
+            for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
                 final int myPss = memInfo.getOtherPss(i);
                 final int mySwappablePss = memInfo.getOtherSwappablePss(i);
                 final int mySharedDirty = memInfo.getOtherSharedDirty(i);
@@ -2132,7 +2080,7 @@
                 final int myPrivateClean = memInfo.getOtherPrivateClean(i);
                 final int mySwappedOut = memInfo.getOtherSwappedOut(i);
                 if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
-                        || mySharedClean != 0 || myPrivateClean != 0) {
+                        || mySharedClean != 0 || myPrivateClean != 0 || mySwappedOut != 0) {
                     if (dumpFullInfo) {
                         printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
                                 myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
@@ -2142,9 +2090,89 @@
                                 myPss, myPrivateDirty,
                                 myPrivateClean, mySwappedOut, "", "", "");
                     }
+                    otherPss -= myPss;
+                    otherSwappablePss -= mySwappablePss;
+                    otherSharedDirty -= mySharedDirty;
+                    otherPrivateDirty -= myPrivateDirty;
+                    otherSharedClean -= mySharedClean;
+                    otherPrivateClean -= myPrivateClean;
+                    otherSwappedOut -= mySwappedOut;
+                }
+            }
+
+            if (dumpFullInfo) {
+                printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
+                        otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
+                        otherSwappedOut, "", "", "");
+                printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
+                        memInfo.getTotalSwappablePss(),
+                        memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
+                        memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
+                        memInfo.getTotalSwappedOut(), nativeMax+dalvikMax,
+                        nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
+            } else {
+                printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
+                        otherPrivateDirty, otherPrivateClean, otherSwappedOut,
+                        "", "", "");
+                printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
+                        memInfo.getTotalPrivateDirty(),
+                        memInfo.getTotalPrivateClean(),
+                        memInfo.getTotalSwappedOut(),
+                        nativeMax+dalvikMax,
+                        nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
+            }
+
+            if (dumpDalvik) {
+                pw.println(" ");
+                pw.println(" Dalvik Details");
+
+                for (int i=Debug.MemoryInfo.NUM_OTHER_STATS;
+                     i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) {
+                    final int myPss = memInfo.getOtherPss(i);
+                    final int mySwappablePss = memInfo.getOtherSwappablePss(i);
+                    final int mySharedDirty = memInfo.getOtherSharedDirty(i);
+                    final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
+                    final int mySharedClean = memInfo.getOtherSharedClean(i);
+                    final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+                    final int mySwappedOut = memInfo.getOtherSwappedOut(i);
+                    if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
+                            || mySharedClean != 0 || myPrivateClean != 0) {
+                        if (dumpFullInfo) {
+                            printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
+                                    myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
+                                    mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
+                        } else {
+                            printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
+                                    myPss, myPrivateDirty,
+                                    myPrivateClean, mySwappedOut, "", "", "");
+                        }
+                    }
                 }
             }
         }
+
+        pw.println(" ");
+        pw.println(" App Summary");
+        printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "Pss(KB)");
+        printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "------");
+        printRow(pw, ONE_COUNT_COLUMN,
+            "Java Heap:", memInfo.getSummaryJavaHeap());
+        printRow(pw, ONE_COUNT_COLUMN,
+            "Native Heap:", memInfo.getSummaryNativeHeap());
+        printRow(pw, ONE_COUNT_COLUMN,
+            "Code:", memInfo.getSummaryCode());
+        printRow(pw, ONE_COUNT_COLUMN,
+            "Stack:", memInfo.getSummaryStack());
+        printRow(pw, ONE_COUNT_COLUMN,
+            "Graphics:", memInfo.getSummaryGraphics());
+        printRow(pw, ONE_COUNT_COLUMN,
+            "Private Other:", memInfo.getSummaryPrivateOther());
+        printRow(pw, ONE_COUNT_COLUMN,
+            "System:", memInfo.getSummarySystem());
+        pw.println(" ");
+        printRow(pw, TWO_COUNT_COLUMNS,
+            "TOTAL:", memInfo.getSummaryTotalPss(),
+            "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
     }
 
     public void registerOnActivityPausedListener(Activity activity,
@@ -4186,9 +4214,14 @@
             if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
                 return;
             }
-            configDiff = mConfiguration.diff(config);
-            mConfiguration.updateFrom(config);
+
+            configDiff = mConfiguration.updateFrom(config);
             config = applyCompatConfiguration(mCurDefaultDisplayDpi);
+
+            final Theme systemTheme = getSystemContext().getTheme();
+            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
+                systemTheme.rebase();
+            }
         }
 
         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 2939322..968c956 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -476,9 +476,8 @@
             tempRect.set(0, 0, width, height);
             view.getMatrix().mapRect(tempRect);
 
-            ViewGroup parent = (ViewGroup) view.getParent();
-            left = leftInParent - tempRect.left + parent.getScrollX();
-            top = topInParent - tempRect.top + parent.getScrollY();
+            left = leftInParent - tempRect.left;
+            top = topInParent - tempRect.top;
             right = left + width;
             bottom = top + height;
         }
@@ -506,7 +505,7 @@
             ViewGroup parent = (ViewGroup) view.getParent();
             Matrix matrix = new Matrix();
             parent.transformMatrixToLocal(matrix);
-
+            matrix.postTranslate(parent.getScrollX(), parent.getScrollY());
             mSharedElementParentMatrices.add(matrix);
         }
     }
@@ -521,6 +520,7 @@
                 // Find the location in the view's parent
                 ViewGroup parent = (ViewGroup) viewParent;
                 parent.transformMatrixToLocal(matrix);
+                matrix.postTranslate(parent.getScrollX(), parent.getScrollY());
             }
         } else {
             // The indices of mSharedElementParentMatrices matches the
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index b6989ab..1461380 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -529,10 +529,12 @@
             boolean checkin = data.readInt() != 0;
             boolean dumpInfo = data.readInt() != 0;
             boolean dumpDalvik = data.readInt() != 0;
+            boolean dumpSummaryOnly = data.readInt() != 0;
             String[] args = data.readStringArray();
             if (fd != null) {
                 try {
-                    dumpMemInfo(fd.getFileDescriptor(), mi, checkin, dumpInfo, dumpDalvik, args);
+                    dumpMemInfo(fd.getFileDescriptor(), mi, checkin, dumpInfo,
+                            dumpDalvik, dumpSummaryOnly, args);
                 } finally {
                     try {
                         fd.close();
@@ -1248,7 +1250,7 @@
     }
 
     public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
-            boolean dumpInfo, boolean dumpDalvik, String[] args) throws RemoteException {
+            boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -1257,6 +1259,7 @@
         data.writeInt(checkin ? 1 : 0);
         data.writeInt(dumpInfo ? 1 : 0);
         data.writeInt(dumpDalvik ? 1 : 0);
+        data.writeInt(dumpSummaryOnly ? 1 : 0);
         data.writeStringArray(args);
         mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index 3abbb5b..a06bc31 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -35,6 +35,7 @@
 import android.view.View;
 import android.view.ViewAssistStructure;
 import android.view.ViewRootImpl;
+import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
 import java.util.ArrayList;
@@ -140,7 +141,14 @@
             mTitle = root.getTitle();
             mRoot = new ViewNode();
             ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
-            view.dispatchProvideAssistStructure(builder);
+            if ((root.getWindowFlags()&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+                // This is a secure window, so it doesn't want a screenshot, and that
+                // means we should also not copy out its view hierarchy.
+                view.onProvideStructure(builder);
+                builder.setAssistBlocked(true);
+                return;
+            }
+            view.dispatchProvideStructure(builder);
         }
 
         WindowNode(Parcel in, PooledStringReader preader) {
@@ -652,7 +660,7 @@
         }
 
         @Override
-        public Bundle editExtras() {
+        public Bundle getExtras() {
             if (mNode.mExtras != null) {
                 return mNode.mExtras;
             }
@@ -661,8 +669,8 @@
         }
 
         @Override
-        public void clearExtras() {
-            mNode.mExtras = null;
+        public boolean hasExtras() {
+            return mNode.mExtras != null;
         }
 
         @Override
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 81a78f6..cb20cb8 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -237,8 +237,11 @@
     }
 
     @Override
-    public void setTheme(int resid) {
-        mThemeResource = resid;
+    public void setTheme(int resId) {
+        if (mThemeResource != resId) {
+            mThemeResource = resId;
+            initializeTheme();
+        }
     }
 
     @Override
@@ -248,15 +251,24 @@
 
     @Override
     public Resources.Theme getTheme() {
-        if (mTheme == null) {
-            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
-                    getOuterContext().getApplicationInfo().targetSdkVersion);
-            mTheme = mResources.newTheme();
-            mTheme.applyStyle(mThemeResource, true);
+        if (mTheme != null) {
+            return mTheme;
         }
+
+        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+                getOuterContext().getApplicationInfo().targetSdkVersion);
+        initializeTheme();
+
         return mTheme;
     }
 
+    private void initializeTheme() {
+        if (mTheme == null) {
+            mTheme = mResources.newTheme();
+        }
+        mTheme.applyStyle(mThemeResource, true);
+    }
+
     @Override
     public ClassLoader getClassLoader() {
         return mPackageInfo != null ?
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 3fb82f6..185578f 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -131,7 +131,7 @@
     void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
     void scheduleTrimMemory(int level) throws RemoteException;
     void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, boolean dumpInfo,
-            boolean dumpDalvik, String[] args) throws RemoteException;
+            boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException;
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void unstableProviderDied(IBinder provider) throws RemoteException;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8009b6c..355f298 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1653,9 +1653,9 @@
     }
 
     /**
-     * Queries whether {@link #DO_NOT_ASK_CREDENTIALS_ON_BOOT} flag is set.
+     * Queries whether {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT} flag is set.
      *
-     * @return true if DO_NOT_ASK_CREDENTIALS_ON_BOOT flag is set.
+     * @return true if RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT flag is set.
      * @hide
      */
     public boolean getDoNotAskCredentialsOnBoot() {
@@ -1753,7 +1753,7 @@
      * is ignored. Once the flag is set, it cannot be reverted back without resetting the
      * device to factory defaults.
      */
-    public static final int DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002;
+    public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002;
 
     /**
      * Force a new device unlock password (the password needed to access the
@@ -1779,7 +1779,7 @@
      *
      * @param password The new password for the user. Null or empty clears the password.
      * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and
-     *              {@link #DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
+     *              {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
      * @return Returns true if the password was applied, or false if it is
      * not acceptable for the current constraints.
      */
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 0a77868..ec6f18d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -28,14 +28,11 @@
 import android.bluetooth.le.ScanResult;
 import android.bluetooth.le.ScanSettings;
 import android.content.Context;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.app.ActivityThread;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.os.Binder;
 import android.util.Log;
 import android.util.Pair;
 
@@ -1255,7 +1252,7 @@
      * @return true if chipset supports on-chip filtering
      */
     public boolean isOffloadedFilteringSupported() {
-        if (getState() != STATE_ON) return false;
+        if (!getLeAccess()) return false;
         try {
             return mService.isOffloadedFilteringSupported();
         } catch (RemoteException e) {
@@ -1270,7 +1267,7 @@
      * @return true if chipset supports on-chip scan batching
      */
     public boolean isOffloadedScanBatchingSupported() {
-        if (getState() != STATE_ON) return false;
+        if (!getLeAccess()) return false;
         try {
             return mService.isOffloadedScanBatchingSupported();
         } catch (RemoteException e) {
@@ -1286,7 +1283,7 @@
      * @hide
      */
     public boolean isHardwareTrackingFiltersAvailable() {
-        if (getState() != STATE_ON) return false;
+        if (!getLeAccess()) return false;
         try {
             IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
             if (iGatt == null) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7ff6ec3..51fa075 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1067,6 +1067,13 @@
     public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device has professional audio level of functionality, performance, and acoustics.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device is capable of communicating with
      * other devices via Bluetooth.
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 525059f..8d96f5c 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -785,6 +785,7 @@
     private native final void deleteTheme(long theme);
     /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
     /*package*/ native static final void copyTheme(long dest, long source);
+    /*package*/ native static final void clearTheme(long theme);
     /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
                                                                 TypedValue outValue,
                                                                 boolean resolve);
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index cde7e84..fecda87 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -1,138 +1,58 @@
 /*
-* 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.content.res;
+ * 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.
+ */
 
-import android.util.ArrayMap;
-import android.util.LongSparseArray;
-import java.lang.ref.WeakReference;
+package android.content.res;
 
 /**
  * A Cache class which can be used to cache resource objects that are easy to clone but more
  * expensive to inflate.
- * @hide
+ *
+ * @hide For internal use only.
  */
-public class ConfigurationBoundResourceCache<T> {
-
-    private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>> mCache =
-            new ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>>();
-
-    final Resources mResources;
+public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<ConstantState<T>> {
+    private final Resources mResources;
 
     /**
-     * Creates a Resource cache for the given Resources instance.
+     * Creates a cache for the given Resources instance.
      *
-     * @param resources The Resource which can be used when creating new instances.
+     * @param resources the resources to use when creating new instances
      */
     public ConfigurationBoundResourceCache(Resources resources) {
         mResources = resources;
     }
 
     /**
-     * Adds a new item to the cache.
+     * If the resource is cached, creates and returns a new instance of it.
      *
-     * @param key A custom key that uniquely identifies the resource.
-     * @param theme The Theme instance where this resource was loaded.
-     * @param constantState The constant state that can create new instances of the resource.
-     *
+     * @param key a key that uniquely identifies the drawable resource
+     * @param theme the theme where the resource will be used
+     * @return a new instance of the resource, or {@code null} if not in
+     *         the cache
      */
-    public void put(long key, Resources.Theme theme, ConstantState<T> constantState) {
-        if (constantState == null) {
-            return;
-        }
-        final String themeKey = theme == null ? "" : theme.getKey();
-        LongSparseArray<WeakReference<ConstantState<T>>> themedCache;
-        synchronized (this) {
-            themedCache = mCache.get(themeKey);
-            if (themedCache == null) {
-                themedCache = new LongSparseArray<WeakReference<ConstantState<T>>>(1);
-                mCache.put(themeKey, themedCache);
-            }
-            themedCache.put(key, new WeakReference<ConstantState<T>>(constantState));
-        }
-    }
-
-    /**
-     * If the resource is cached, creates a new instance of it and returns.
-     *
-     * @param key The long key which can be used to uniquely identify the resource.
-     * @param theme The The Theme instance where we want to load this resource.
-     *
-     * @return If this resources was loaded before, returns a new instance of it. Otherwise, returns
-     *         null.
-     */
-    public T get(long key, Resources.Theme theme) {
-        final String themeKey = theme != null ? theme.getKey() : "";
-        final LongSparseArray<WeakReference<ConstantState<T>>> themedCache;
-        final WeakReference<ConstantState<T>> wr;
-        synchronized (this) {
-            themedCache = mCache.get(themeKey);
-            if (themedCache == null) {
-                return null;
-            }
-            wr = themedCache.get(key);
-        }
-        if (wr == null) {
-            return null;
-        }
-        final ConstantState entry = wr.get();
+    public T getInstance(long key, Resources.Theme theme) {
+        final ConstantState<T> entry = get(key, theme);
         if (entry != null) {
-            return  (T) entry.newInstance(mResources, theme);
-        } else {  // our entry has been purged
-            synchronized (this) {
-                // there is a potential race condition here where this entry may be put in
-                // another thread. But we prefer it to minimize lock duration
-                themedCache.delete(key);
-            }
+            return entry.newInstance(mResources, theme);
         }
+
         return null;
     }
 
-    /**
-     * Users of ConfigurationBoundResourceCache must call this method whenever a configuration
-     * change happens. On this callback, the cache invalidates all resources that are not valid
-     * anymore.
-     *
-     * @param configChanges The configuration changes
-     */
-    public void onConfigurationChange(final int configChanges) {
-        synchronized (this) {
-            final int size = mCache.size();
-            for (int i = size - 1; i >= 0; i--) {
-                final LongSparseArray<WeakReference<ConstantState<T>>>
-                        themeCache = mCache.valueAt(i);
-                onConfigurationChangeInt(themeCache, configChanges);
-                if (themeCache.size() == 0) {
-                    mCache.removeAt(i);
-                }
-            }
-        }
+    @Override
+    public boolean shouldInvalidateEntry(ConstantState<T> entry, int configChanges) {
+        return Configuration.needNewResources(configChanges, entry.getChangingConfigurations());
     }
-
-    private void onConfigurationChangeInt(
-            final LongSparseArray<WeakReference<ConstantState<T>>> themeCache,
-            final int configChanges) {
-        final int size = themeCache.size();
-        for (int i = size - 1; i >= 0; i--) {
-            final WeakReference<ConstantState<T>> wr = themeCache.valueAt(i);
-            final ConstantState<T> constantState = wr.get();
-            if (constantState == null || Configuration.needNewResources(
-                    configChanges, constantState.getChangingConfigurations())) {
-                themeCache.removeAt(i);
-            }
-        }
-    }
-
 }
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
new file mode 100644
index 0000000..fc70bc6
--- /dev/null
+++ b/core/java/android/content/res/DrawableCache.java
@@ -0,0 +1,57 @@
+/*
+ * 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.content.res;
+
+import android.graphics.drawable.Drawable;
+
+/**
+ * Class which can be used to cache Drawable resources against a theme.
+ */
+class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> {
+    private final Resources mResources;
+
+    /**
+     * Creates a cache for the given Resources instance.
+     *
+     * @param resources the resources to use when creating new instances
+     */
+    public DrawableCache(Resources resources) {
+        mResources = resources;
+    }
+
+    /**
+     * If the resource is cached, creates and returns a new instance of it.
+     *
+     * @param key a key that uniquely identifies the drawable resource
+     * @param theme the theme where the resource will be used
+     * @return a new instance of the resource, or {@code null} if not in
+     *         the cache
+     */
+    public Drawable getInstance(long key, Resources.Theme theme) {
+        final Drawable.ConstantState entry = get(key, theme);
+        if (entry != null) {
+            return entry.newDrawable(mResources, theme);
+        }
+
+        return null;
+    }
+
+    @Override
+    public boolean shouldInvalidateEntry(Drawable.ConstantState entry, int configChanges) {
+        return false;
+    }
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ae41b69..a572590 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -20,6 +20,7 @@
 import android.annotation.ColorInt;
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
+import com.android.internal.util.GrowingArrayUtils;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -60,6 +61,7 @@
 import android.util.Slog;
 import android.util.TypedValue;
 import android.view.ViewDebug;
+import android.view.ViewHierarchyEncoder;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -132,10 +134,8 @@
     // These are protected by mAccessLock.
     private final Object mAccessLock = new Object();
     private final Configuration mTmpConfig = new Configuration();
-    private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mDrawableCache =
-            new ArrayMap<>();
-    private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mColorDrawableCache =
-            new ArrayMap<>();
+    private final DrawableCache mDrawableCache = new DrawableCache(this);
+    private final DrawableCache mColorDrawableCache = new DrawableCache(this);
     private final ConfigurationBoundResourceCache<ColorStateList> mColorStateListCache =
             new ConfigurationBoundResourceCache<>(this);
     private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
@@ -1441,7 +1441,7 @@
             AssetManager.applyThemeStyle(mTheme, resId, force);
 
             mThemeResId = resId;
-            mKey += Integer.toHexString(resId) + (force ? "! " : " ");
+            mKey.append(resId, force);
         }
 
         /**
@@ -1457,7 +1457,7 @@
             AssetManager.copyTheme(mTheme, other.mTheme);
 
             mThemeResId = other.mThemeResId;
-            mKey = other.mKey;
+            mKey.setTo(other.getKey());
         }
 
         /**
@@ -1765,6 +1765,9 @@
             mTheme = mAssets.createTheme();
         }
 
+        /** Unique key for the series of styles applied to this theme. */
+        private final ThemeKey mKey = new ThemeKey();
+
         @SuppressWarnings("hiding")
         private final AssetManager mAssets;
         private final long mTheme;
@@ -1772,9 +1775,6 @@
         /** Resource identifier for the theme. */
         private int mThemeResId = 0;
 
-        /** Unique key for the series of styles applied to this theme. */
-        private String mKey = "";
-
         // Needed by layoutlib.
         /*package*/ long getNativeTheme() {
             return mTheme;
@@ -1784,7 +1784,7 @@
             return mThemeResId;
         }
 
-        /*package*/ String getKey() {
+        /*package*/ ThemeKey getKey() {
             return mKey;
         }
 
@@ -1793,29 +1793,133 @@
         }
 
         /**
-         * Parses {@link #mKey} and returns a String array that holds pairs of adjacent Theme data:
-         * resource name followed by whether or not it was forced, as specified by
-         * {@link #applyStyle(int, boolean)}.
+         * Parses {@link #mKey} and returns a String array that holds pairs of
+         * adjacent Theme data: resource name followed by whether or not it was
+         * forced, as specified by {@link #applyStyle(int, boolean)}.
          *
          * @hide
          */
         @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
         public String[] getTheme() {
-            String[] themeData = mKey.split(" ");
-            String[] themes = new String[themeData.length * 2];
-            String theme;
-            boolean forced;
-
-            for (int i = 0, j = themeData.length - 1; i < themes.length; i += 2, --j) {
-                theme = themeData[j];
-                forced = theme.endsWith("!");
-                themes[i] = forced ?
-                        getResourceNameFromHexString(theme.substring(0, theme.length() - 1)) :
-                        getResourceNameFromHexString(theme);
+            final int N = mKey.mCount;
+            final String[] themes = new String[N * 2];
+            for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
+                final int resId = mKey.mResId[j];
+                final boolean forced = mKey.mForce[j];
+                try {
+                    themes[i] = getResourceName(resId);
+                } catch (NotFoundException e) {
+                    themes[i] = Integer.toHexString(i);
+                }
                 themes[i + 1] = forced ? "forced" : "not forced";
             }
             return themes;
         }
+
+        /** @hide */
+        public void encode(@NonNull ViewHierarchyEncoder encoder) {
+            encoder.beginObject(this);
+            final String[] properties = getTheme();
+            for (int i = 0; i < properties.length; i += 2) {
+                encoder.addProperty(properties[i], properties[i+1]);
+            }
+            encoder.endObject();
+        }
+
+        /**
+         * Rebases the theme against the parent Resource object's current
+         * configuration by re-applying the styles passed to
+         * {@link #applyStyle(int, boolean)}.
+         *
+         * @hide
+         */
+        public void rebase() {
+            AssetManager.clearTheme(mTheme);
+
+            // Reapply the same styles in the same order.
+            for (int i = 0; i < mKey.mCount; i++) {
+                final int resId = mKey.mResId[i];
+                final boolean force = mKey.mForce[i];
+                AssetManager.applyThemeStyle(mTheme, resId, force);
+            }
+        }
+    }
+
+    static class ThemeKey implements Cloneable {
+        int[] mResId;
+        boolean[] mForce;
+        int mCount;
+
+        private int mHashCode = 0;
+
+        public void append(int resId, boolean force) {
+            if (mResId == null) {
+                mResId = new int[4];
+            }
+
+            if (mForce == null) {
+                mForce = new boolean[4];
+            }
+
+            mResId = GrowingArrayUtils.append(mResId, mCount, resId);
+            mForce = GrowingArrayUtils.append(mForce, mCount, force);
+            mCount++;
+
+            mHashCode = 31 * (31 * mHashCode + resId) + (force ? 1 : 0);
+        }
+
+        /**
+         * Sets up this key as a deep copy of another key.
+         *
+         * @param other the key to deep copy into this key
+         */
+        public void setTo(ThemeKey other) {
+            mResId = other.mResId == null ? null : other.mResId.clone();
+            mForce = other.mForce == null ? null : other.mForce.clone();
+            mCount = other.mCount;
+        }
+
+        @Override
+        public int hashCode() {
+            return mHashCode;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+
+            if (o == null || getClass() != o.getClass() || hashCode() != o.hashCode()) {
+                return false;
+            }
+
+            final ThemeKey t = (ThemeKey) o;
+            if (mCount != t.mCount) {
+                return false;
+            }
+
+            final int N = mCount;
+            for (int i = 0; i < N; i++) {
+                if (mResId[i] != t.mResId[i] || mForce[i] != t.mForce[i]) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        /**
+         * @return a shallow copy of this key
+         */
+        @Override
+        public ThemeKey clone() {
+            final ThemeKey other = new ThemeKey();
+            other.mResId = mResId;
+            other.mForce = mForce;
+            other.mCount = mCount;
+            return other;
+        }
     }
 
     /**
@@ -1944,8 +2048,8 @@
                         + " final compat is " + mCompatibilityInfo);
             }
 
-            clearDrawableCachesLocked(mDrawableCache, configChanges);
-            clearDrawableCachesLocked(mColorDrawableCache, configChanges);
+            mDrawableCache.onConfigurationChange(configChanges);
+            mColorDrawableCache.onConfigurationChange(configChanges);
             mColorStateListCache.onConfigurationChange(configChanges);
             mAnimatorCache.onConfigurationChange(configChanges);
             mStateListAnimatorCache.onConfigurationChange(configChanges);
@@ -1983,48 +2087,6 @@
         return configChanges;
     }
 
-    private void clearDrawableCachesLocked(
-            ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
-            int configChanges) {
-        final int N = caches.size();
-        for (int i = 0; i < N; i++) {
-            clearDrawableCacheLocked(caches.valueAt(i), configChanges);
-        }
-    }
-
-    private void clearDrawableCacheLocked(
-            LongSparseArray<WeakReference<ConstantState>> cache, int configChanges) {
-        if (DEBUG_CONFIG) {
-            Log.d(TAG, "Cleaning up drawables config changes: 0x"
-                    + Integer.toHexString(configChanges));
-        }
-        final int N = cache.size();
-        for (int i = 0; i < N; i++) {
-            final WeakReference<ConstantState> ref = cache.valueAt(i);
-            if (ref != null) {
-                final ConstantState cs = ref.get();
-                if (cs != null) {
-                    if (Configuration.needNewResources(
-                            configChanges, cs.getChangingConfigurations())) {
-                        if (DEBUG_CONFIG) {
-                            Log.d(TAG, "FLUSHING #0x"
-                                    + Long.toHexString(cache.keyAt(i))
-                                    + " / " + cs + " with changes: 0x"
-                                    + Integer.toHexString(cs.getChangingConfigurations()));
-                        }
-                        cache.setValueAt(i, null);
-                    } else if (DEBUG_CONFIG) {
-                        Log.d(TAG, "(Keeping #0x"
-                                + Long.toHexString(cache.keyAt(i))
-                                + " / " + cs + " with changes: 0x"
-                                + Integer.toHexString(cs.getChangingConfigurations())
-                                + ")");
-                    }
-                }
-            }
-        }
-    }
-
     /**
      * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
      * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
@@ -2436,7 +2498,7 @@
         }
 
         final boolean isColorDrawable;
-        final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches;
+        final DrawableCache caches;
         final long key;
         if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
                 && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
@@ -2452,7 +2514,7 @@
         // First, check whether we have a cached version of this drawable
         // that was inflated against the specified theme.
         if (!mPreloading) {
-            final Drawable cachedDrawable = getCachedDrawable(caches, key, theme);
+            final Drawable cachedDrawable = caches.getInstance(key, theme);
             if (cachedDrawable != null) {
                 return cachedDrawable;
             }
@@ -2479,13 +2541,8 @@
         // Determine if the drawable has unresolved theme attributes. If it
         // does, we'll need to apply a theme and store it in a theme-specific
         // cache.
-        final String cacheKey;
-        if (!dr.canApplyTheme()) {
-            cacheKey = CACHE_NOT_THEMED;
-        } else if (theme == null) {
-            cacheKey = CACHE_NULL_THEME;
-        } else {
-            cacheKey = theme.getKey();
+        final boolean canApplyTheme = dr.canApplyTheme();
+        if (canApplyTheme && theme != null) {
             dr = dr.mutate();
             dr.applyTheme(theme);
             dr.clearMutated();
@@ -2495,15 +2552,14 @@
         // cache: preload, not themed, null theme, or theme-specific.
         if (dr != null) {
             dr.setChangingConfigurations(value.changingConfigurations);
-            cacheDrawable(value, isColorDrawable, caches, cacheKey, key, dr);
+            cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
         }
 
         return dr;
     }
 
-    private void cacheDrawable(TypedValue value, boolean isColorDrawable,
-            ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
-            String cacheKey, long key, Drawable dr) {
+    private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
+            Theme theme, boolean usesTheme, long key, Drawable dr) {
         final ConstantState cs = dr.getConstantState();
         if (cs == null) {
             return;
@@ -2531,54 +2587,12 @@
             }
         } else {
             synchronized (mAccessLock) {
-                LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(cacheKey);
-                if (themedCache == null) {
-                    // Clean out the caches before we add more. This shouldn't
-                    // happen very often.
-                    pruneCaches(caches);
-                    themedCache = new LongSparseArray<>(1);
-                    caches.put(cacheKey, themedCache);
-                }
-                themedCache.put(key, new WeakReference<>(cs));
+                caches.put(key, theme, cs, usesTheme);
             }
         }
     }
 
     /**
-     * Prunes empty caches from the cache map.
-     *
-     * @param caches The map of caches to prune.
-     */
-    private void pruneCaches(ArrayMap<String,
-            LongSparseArray<WeakReference<ConstantState>>> caches) {
-        final int N = caches.size();
-        for (int i = N - 1; i >= 0; i--) {
-            final LongSparseArray<WeakReference<ConstantState>> cache = caches.valueAt(i);
-            if (pruneCache(cache)) {
-                caches.removeAt(i);
-            }
-        }
-    }
-
-    /**
-     * Prunes obsolete weak references from a cache, returning {@code true} if
-     * the cache is empty and should be removed.
-     *
-     * @param cache The cache of weak references to prune.
-     * @return {@code true} if the cache is empty and should be removed.
-     */
-    private boolean pruneCache(LongSparseArray<WeakReference<ConstantState>> cache) {
-        final int N = cache.size();
-        for (int i = N - 1; i >= 0; i--) {
-            final WeakReference entry = cache.valueAt(i);
-            if (entry == null || entry.get() == null) {
-                cache.removeAt(i);
-            }
-        }
-        return cache.size() == 0;
-    }
-
-    /**
      * Loads a drawable from XML or resources stream.
      */
     private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
@@ -2631,51 +2645,6 @@
         return dr;
     }
 
-    private Drawable getCachedDrawable(
-            ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
-            long key, Theme theme) {
-        synchronized (mAccessLock) {
-            // First search theme-agnostic cache.
-            final Drawable unthemedDrawable = getCachedDrawableLocked(
-                    caches, key, CACHE_NOT_THEMED);
-            if (unthemedDrawable != null) {
-                return unthemedDrawable;
-            }
-
-            // Next search theme-specific cache.
-            final String themeKey = theme != null ? theme.getKey() : CACHE_NULL_THEME;
-            return getCachedDrawableLocked(caches, key, themeKey);
-        }
-    }
-
-    private Drawable getCachedDrawableLocked(
-            ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
-            long key, String themeKey) {
-        final LongSparseArray<WeakReference<ConstantState>> cache = caches.get(themeKey);
-        if (cache != null) {
-            final ConstantState entry = getConstantStateLocked(cache, key);
-            if (entry != null) {
-                return entry.newDrawable(this);
-            }
-        }
-        return null;
-    }
-
-    private ConstantState getConstantStateLocked(
-            LongSparseArray<WeakReference<ConstantState>> drawableCache, long key) {
-        final WeakReference<ConstantState> wr = drawableCache.get(key);
-        if (wr != null) {
-            final ConstantState entry = wr.get();
-            if (entry != null) {
-                return entry;
-            } else {
-                // Our entry has been purged.
-                drawableCache.delete(key);
-            }
-        }
-        return null;
-    }
-
     @Nullable
     ColorStateList loadColorStateList(TypedValue value, int id, Theme theme)
             throws NotFoundException {
@@ -2713,8 +2682,7 @@
         }
 
         final ConfigurationBoundResourceCache<ColorStateList> cache = mColorStateListCache;
-
-        csl = cache.get(key, theme);
+        csl = cache.getInstance(key, theme);
         if (csl != null) {
             return csl;
         }
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
new file mode 100644
index 0000000..9a2d06147
--- /dev/null
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -0,0 +1,233 @@
+/*
+ * 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.content.res;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources.Theme;
+import android.content.res.Resources.ThemeKey;
+import android.util.LongSparseArray;
+import android.util.ArrayMap;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Data structure used for caching data against themes.
+ *
+ * @param <T> type of data to cache
+ */
+abstract class ThemedResourceCache<T> {
+    private ArrayMap<ThemeKey, LongSparseArray<WeakReference<T>>> mThemedEntries;
+    private LongSparseArray<WeakReference<T>> mUnthemedEntries;
+    private LongSparseArray<WeakReference<T>> mNullThemedEntries;
+
+    /**
+     * Adds a new theme-dependent entry to the cache.
+     *
+     * @param key a key that uniquely identifies the entry
+     * @param theme the theme against which this entry was inflated, or
+     *              {@code null} if the entry has no theme applied
+     * @param entry the entry to cache
+     */
+    public void put(long key, @Nullable Theme theme, @NonNull T entry) {
+        put(key, theme, entry, true);
+    }
+
+    /**
+     * Adds a new entry to the cache.
+     *
+     * @param key a key that uniquely identifies the entry
+     * @param theme the theme against which this entry was inflated, or
+     *              {@code null} if the entry has no theme applied
+     * @param entry the entry to cache
+     * @param usesTheme {@code true} if the entry is affected theme changes,
+     *                  {@code false} otherwise
+     */
+    public void put(long key, @Nullable Theme theme, @NonNull T entry, boolean usesTheme) {
+        if (entry == null) {
+            return;
+        }
+
+        synchronized (this) {
+            final LongSparseArray<WeakReference<T>> entries;
+            if (!usesTheme) {
+                entries = getUnthemedLocked(true);
+            } else {
+                entries = getThemedLocked(theme, true);
+            }
+            if (entries != null) {
+                entries.put(key, new WeakReference<>(entry));
+            }
+        }
+    }
+
+    /**
+     * Returns an entry from the cache.
+     *
+     * @param key a key that uniquely identifies the entry
+     * @param theme the theme where the entry will be used
+     * @return a cached entry, or {@code null} if not in the cache
+     */
+    @Nullable
+    public T get(long key, @Nullable Theme theme) {
+        // The themed (includes null-themed) and unthemed caches are mutually
+        // exclusive, so we'll give priority to whichever one we think we'll
+        // hit first. Since most of the framework drawables are themed, that's
+        // probably going to be the themed cache.
+        synchronized (this) {
+            final LongSparseArray<WeakReference<T>> themedEntries = getThemedLocked(theme, false);
+            if (themedEntries != null) {
+                final WeakReference<T> themedEntry = themedEntries.get(key);
+                if (themedEntry != null) {
+                    return themedEntry.get();
+                }
+            }
+
+            final LongSparseArray<WeakReference<T>> unthemedEntries = getUnthemedLocked(false);
+            if (unthemedEntries != null) {
+                final WeakReference<T> unthemedEntry = unthemedEntries.get(key);
+                if (unthemedEntry != null) {
+                    return unthemedEntry.get();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Prunes cache entries that have been invalidated by a configuration
+     * change.
+     *
+     * @param configChanges a bitmask of configuration changes
+     */
+    public void onConfigurationChange(int configChanges) {
+        prune(configChanges);
+    }
+
+    /**
+     * Returns whether a cached entry has been invalidated by a configuration
+     * change.
+     *
+     * @param entry a cached entry
+     * @param configChanges a non-zero bitmask of configuration changes
+     * @return {@code true} if the entry is invalid, {@code false} otherwise
+     */
+    protected abstract boolean shouldInvalidateEntry(@NonNull T entry, int configChanges);
+
+    /**
+     * Returns the cached data for the specified theme, optionally creating a
+     * new entry if one does not already exist.
+     *
+     * @param t the theme for which to return cached data
+     * @param create {@code true} to create an entry if one does not already
+     *               exist, {@code false} otherwise
+     * @return the cached data for the theme, or {@code null} if the cache is
+     *         empty and {@code create} was {@code false}
+     */
+    @Nullable
+    private LongSparseArray<WeakReference<T>> getThemedLocked(@Nullable Theme t, boolean create) {
+        if (t == null) {
+            if (mNullThemedEntries == null && create) {
+                mNullThemedEntries = new LongSparseArray<>(1);
+            }
+            return mNullThemedEntries;
+        }
+
+        if (mThemedEntries == null) {
+            if (create) {
+                mThemedEntries = new ArrayMap<>(1);
+            } else {
+                return null;
+            }
+        }
+
+        final ThemeKey key = t.getKey();
+        LongSparseArray<WeakReference<T>> cache = mThemedEntries.get(key);
+        if (cache == null && create) {
+            cache = new LongSparseArray<>(1);
+
+            final ThemeKey keyClone = key.clone();
+            mThemedEntries.put(keyClone, cache);
+        }
+
+        return cache;
+    }
+
+    /**
+     * Returns the theme-agnostic cached data.
+     *
+     * @param create {@code true} to create an entry if one does not already
+     *               exist, {@code false} otherwise
+     * @return the theme-agnostic cached data, or {@code null} if the cache is
+     *         empty and {@code create} was {@code false}
+     */
+    @Nullable
+    private LongSparseArray<WeakReference<T>> getUnthemedLocked(boolean create) {
+        if (mUnthemedEntries == null && create) {
+            mUnthemedEntries = new LongSparseArray<>(1);
+        }
+        return mUnthemedEntries;
+    }
+
+    /**
+     * Prunes cache entries affected by configuration changes or where weak
+     * references have expired.
+     *
+     * @param configChanges a bitmask of configuration changes, or {@code 0} to
+     *                      simply prune missing weak references
+     * @return {@code true} if the cache is completely empty after pruning
+     */
+    private boolean prune(int configChanges) {
+        synchronized (this) {
+            if (mThemedEntries != null) {
+                for (int i = mThemedEntries.size() - 1; i >= 0; i--) {
+                    if (pruneEntriesLocked(mThemedEntries.valueAt(i), configChanges)) {
+                        mThemedEntries.removeAt(i);
+                    }
+                }
+            }
+
+            pruneEntriesLocked(mNullThemedEntries, configChanges);
+            pruneEntriesLocked(mUnthemedEntries, configChanges);
+
+            return mThemedEntries == null && mNullThemedEntries == null
+                    && mUnthemedEntries == null;
+        }
+    }
+
+    private boolean pruneEntriesLocked(@Nullable LongSparseArray<WeakReference<T>> entries,
+            int configChanges) {
+        if (entries == null) {
+            return true;
+        }
+
+        for (int i = entries.size() - 1; i >= 0; i--) {
+            final WeakReference<T> ref = entries.valueAt(i);
+            if (ref == null || pruneEntryLocked(ref.get(), configChanges)) {
+                entries.removeAt(i);
+            }
+        }
+
+        return entries.size() == 0;
+    }
+
+    private boolean pruneEntryLocked(@Nullable T entry, int configChanges) {
+        return entry == null || (configChanges != 0
+                && shouldInvalidateEntry(entry, configChanges));
+    }
+}
diff --git a/core/java/android/ddm/DdmHandleViewDebug.java b/core/java/android/ddm/DdmHandleViewDebug.java
index 3a36b0a..be48633 100644
--- a/core/java/android/ddm/DdmHandleViewDebug.java
+++ b/core/java/android/ddm/DdmHandleViewDebug.java
@@ -229,15 +229,25 @@
     private Chunk dumpHierarchy(View rootView, ByteBuffer in) {
         boolean skipChildren = in.getInt() > 0;
         boolean includeProperties = in.getInt() > 0;
+        boolean v2 = in.hasRemaining() && in.getInt() > 0;
 
-        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
+        long start = System.currentTimeMillis();
+
+        ByteArrayOutputStream b = new ByteArrayOutputStream(2*1024*1024);
         try {
-            ViewDebug.dump(rootView, skipChildren, includeProperties, b);
-        } catch (IOException e) {
+            if (v2) {
+                ViewDebug.dumpv2(rootView, b);
+            } else {
+                ViewDebug.dump(rootView, skipChildren, includeProperties, b);
+            }
+        } catch (IOException | InterruptedException e) {
             return createFailChunk(1, "Unexpected error while obtaining view hierarchy: "
                     + e.getMessage());
         }
 
+        long end = System.currentTimeMillis();
+        Log.d(TAG, "Time to obtain view hierarchy (ms): " + (end - start));
+
         byte[] data = b.toByteArray();
         return new Chunk(CHUNK_VURT, data, 0, data.length);
     }
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index aeddf03..ef71c42 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -212,8 +212,7 @@
      * <p>All capture sessions can be used for capturing images from the camera but only capture
      * sessions created by
      * {@link CameraDevice#createReprocessibleCaptureSession createReprocessibleCaptureSession}
-     * can submit reprocess capture requests. The list of requests must all be capturing images from
-     * the camera or all be reprocess capture requests. Submitting a reprocess request to a regular
+     * can submit reprocess capture requests. Submitting a reprocess request to a regular
      * capture session will result in an {@link IllegalArgumentException}.</p>
      *
      * @param requests the list of settings for this burst capture
@@ -236,9 +235,7 @@
      * @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 the list of requests contains both requests to
-     *                                  capture images from the camera and reprocess capture
-     *                                  requests; or one of the reprocess capture requests was
+     *                                  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
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 3c19529..dff6227 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -177,26 +177,20 @@
     public synchronized int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
             Handler handler) throws CameraAccessException {
         if (requests == null) {
-            throw new IllegalArgumentException("requests must not be null");
+            throw new IllegalArgumentException("Requests must not be null");
         } else if (requests.isEmpty()) {
-            throw new IllegalArgumentException("requests must have at least one element");
+            throw new IllegalArgumentException("Requests must have at least one element");
         }
 
-        boolean reprocess = requests.get(0).isReprocess();
-        if (reprocess && !isReprocessible()) {
-            throw new IllegalArgumentException("this capture session cannot handle reprocess " +
-                    "requests");
-        } else if (reprocess && requests.get(0).getReprocessibleSessionId() != mId) {
-            throw new IllegalArgumentException("capture request was created for another session");
-        }
-
-        for (int i = 1; i < requests.size(); i++) {
-            if (requests.get(i).isReprocess() != reprocess) {
-                throw new IllegalArgumentException("cannot mix regular and reprocess capture " +
-                        " requests");
-            } else if (reprocess && requests.get(i).getReprocessibleSessionId() != mId) {
-                throw new IllegalArgumentException("capture request was created for another " +
-                    "session");
+        for (CaptureRequest request : requests) {
+            if (request.isReprocess()) {
+                if (!isReprocessible()) {
+                    throw new IllegalArgumentException("This capture session cannot handle " +
+                            "reprocess requests");
+                } else if (request.getReprocessibleSessionId() != mId) {
+                    throw new IllegalArgumentException("Capture request was created for another " +
+                            "session");
+                }
             }
         }
 
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index ff4ad79..e84b46a 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -94,11 +94,11 @@
     private final int mTotalPartialCount;
 
     /**
-     * A list tracking request and its expected last frame.
-     * Updated when calling ICameraDeviceUser methods.
+     * A list tracking request and its expected last regular frame number and last reprocess frame
+     * number. Updated when calling ICameraDeviceUser methods.
      */
-    private final List<SimpleEntry</*frameNumber*/Long, /*requestId*/Integer>>
-            mFrameNumberRequestPairs = new ArrayList<SimpleEntry<Long, Integer>>();
+    private final List<RequestLastFrameNumbersHolder> mRequestLastFrameNumbersList =
+            new ArrayList<>();
 
     /**
      * An object tracking received frame numbers.
@@ -653,8 +653,8 @@
      *
      * <p>If lastFrameNumber is NO_FRAMES_CAPTURED, it means that the request was never
      * sent to HAL. Then onCaptureSequenceAborted is immediately triggered.
-     * If lastFrameNumber is non-negative, then the requestId and lastFrameNumber pair
-     * is added to the list mFrameNumberRequestPairs.</p>
+     * If lastFrameNumber is non-negative, then the requestId and lastFrameNumber as the last
+     * regular frame number will be added to the list mRequestLastFrameNumbersList.</p>
      *
      * @param requestId the request ID of the current repeating request.
      *
@@ -693,10 +693,6 @@
                                         "early trigger sequence complete for request %d",
                                         requestId));
                             }
-                            if (lastFrameNumber < Integer.MIN_VALUE
-                                    || lastFrameNumber > Integer.MAX_VALUE) {
-                                throw new AssertionError(lastFrameNumber + " cannot be cast to int");
-                            }
                             holder.getCallback().onCaptureSequenceAborted(
                                     CameraDeviceImpl.this,
                                     requestId);
@@ -710,9 +706,11 @@
                         requestId));
             }
         } else {
-            mFrameNumberRequestPairs.add(
-                    new SimpleEntry<Long, Integer>(lastFrameNumber,
-                            requestId));
+            // This function is only called for regular request so lastFrameNumber is the last
+            // regular frame number.
+            mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestId,
+                    lastFrameNumber));
+
             // It is possible that the last frame has already arrived, so we need to check
             // for sequence completion right away
             checkAndFireSequenceComplete();
@@ -779,8 +777,8 @@
                 }
                 mRepeatingRequestId = requestId;
             } else {
-                mFrameNumberRequestPairs.add(
-                        new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
+                mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestList,
+                        requestId, lastFrameNumber));
             }
 
             if (mIdle) {
@@ -1146,7 +1144,101 @@
         public int getSessionId() {
             return mSessionId;
         }
+    }
 
+    /**
+     * This class holds a capture ID and its expected last regular frame number and last reprocess
+     * frame number.
+     */
+    static class RequestLastFrameNumbersHolder {
+        // request ID
+        private final int mRequestId;
+        // The last regular frame number for this request ID. It's
+        // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no regular request.
+        private final long mLastRegularFrameNumber;
+        // The last reprocess frame number for this request ID. It's
+        // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no reprocess request.
+        private final long mLastReprocessFrameNumber;
+
+        /**
+         * Create a request-last-frame-numbers holder with a list of requests, request ID, and
+         * the last frame number returned by camera service.
+         */
+        public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, int requestId,
+                long lastFrameNumber) {
+            long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+            long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+            long frameNumber = lastFrameNumber;
+
+            if (lastFrameNumber < requestList.size() - 1) {
+                throw new IllegalArgumentException("lastFrameNumber: " + lastFrameNumber +
+                        " should be at least " + (requestList.size() - 1) + " for the number of " +
+                        " requests in the list: " + requestList.size());
+            }
+
+            // find the last regular frame number and the last reprocess frame number
+            for (int i = requestList.size() - 1; i >= 0; i--) {
+                CaptureRequest request = requestList.get(i);
+                if (request.isReprocess() && lastReprocessFrameNumber ==
+                        CaptureCallback.NO_FRAMES_CAPTURED) {
+                    lastReprocessFrameNumber = frameNumber;
+                } else if (!request.isReprocess() && lastRegularFrameNumber ==
+                        CaptureCallback.NO_FRAMES_CAPTURED) {
+                    lastRegularFrameNumber = frameNumber;
+                }
+
+                if (lastReprocessFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED &&
+                        lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
+                    break;
+                }
+
+                frameNumber--;
+            }
+
+            mLastRegularFrameNumber = lastRegularFrameNumber;
+            mLastReprocessFrameNumber = lastReprocessFrameNumber;
+            mRequestId = requestId;
+        }
+
+        /**
+         * Create a request-last-frame-numbers holder with a request ID and last regular frame
+         * number.
+         */
+        public RequestLastFrameNumbersHolder(int requestId, long lastRegularFrameNumber) {
+            mLastRegularFrameNumber = lastRegularFrameNumber;
+            mLastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+            mRequestId = requestId;
+        }
+
+        /**
+         * Return the last regular frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
+         * it contains no regular request.
+         */
+        public long getLastRegularFrameNumber() {
+            return mLastRegularFrameNumber;
+        }
+
+        /**
+         * Return the last reprocess frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
+         * it contains no reprocess request.
+         */
+        public long getLastReprocessFrameNumber() {
+            return mLastReprocessFrameNumber;
+        }
+
+        /**
+         * Return the last frame number overall.
+         */
+        public long getLastFrameNumber() {
+            return Math.max(mLastRegularFrameNumber, mLastReprocessFrameNumber);
+        }
+
+        /**
+         * Return the request ID.
+         */
+        public int getRequestId() {
+            return mRequestId;
+        }
     }
 
     /**
@@ -1154,8 +1246,8 @@
      */
     public class FrameNumberTracker {
 
-        private long mCompletedFrameNumber = -1;
-        private long mCompletedReprocessFrameNumber = -1;
+        private long mCompletedFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+        private long mCompletedReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
         /** the skipped frame numbers that belong to regular results */
         private final LinkedList<Long> mSkippedRegularFrameNumbers = new LinkedList<Long>();
         /** the skipped frame numbers that belong to reprocess results */
@@ -1360,11 +1452,11 @@
         long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
         long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
         boolean isReprocess = false;
-        Iterator<SimpleEntry<Long, Integer> > iter = mFrameNumberRequestPairs.iterator();
+        Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
         while (iter.hasNext()) {
-            final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
+            final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
             boolean sequenceCompleted = false;
-            final int requestId = frameNumberRequestPair.getValue();
+            final int requestId = requestLastFrameNumbers.getRequestId();
             final CaptureCallbackHolder holder;
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) {
@@ -1376,19 +1468,22 @@
                 holder = (index >= 0) ?
                         mCaptureCallbackMap.valueAt(index) : null;
                 if (holder != null) {
-                    isReprocess = holder.getRequest().isReprocess();
+                    long lastRegularFrameNumber =
+                            requestLastFrameNumbers.getLastRegularFrameNumber();
+                    long lastReprocessFrameNumber =
+                            requestLastFrameNumbers.getLastReprocessFrameNumber();
+
                     // check if it's okay to remove request from mCaptureCallbackMap
-                    if ((isReprocess && frameNumberRequestPair.getKey() <=
-                            completedReprocessFrameNumber) || (!isReprocess &&
-                            frameNumberRequestPair.getKey() <= completedFrameNumber)) {
+                    if (lastRegularFrameNumber <= completedFrameNumber &&
+                            lastReprocessFrameNumber <= completedReprocessFrameNumber) {
                         sequenceCompleted = true;
                         mCaptureCallbackMap.removeAt(index);
                         if (DEBUG) {
                             Log.v(TAG, String.format(
-                                    "remove holder for requestId %d, "
-                                    + "because lastFrame %d is <= %d",
-                                    requestId, frameNumberRequestPair.getKey(),
-                                    completedFrameNumber));
+                                    "Remove holder for requestId %d, because lastRegularFrame %d " +
+                                    "is <= %d and lastReprocessFrame %d is <= %d", requestId,
+                                    lastRegularFrameNumber, completedFrameNumber,
+                                    lastReprocessFrameNumber, completedReprocessFrameNumber));
                         }
                     }
                 }
@@ -1412,16 +1507,10 @@
                                         requestId));
                             }
 
-                            long lastFrameNumber = frameNumberRequestPair.getKey();
-                            if (lastFrameNumber < Integer.MIN_VALUE
-                                    || lastFrameNumber > Integer.MAX_VALUE) {
-                                throw new AssertionError(lastFrameNumber
-                                        + " cannot be cast to int");
-                            }
                             holder.getCallback().onCaptureSequenceCompleted(
                                 CameraDeviceImpl.this,
                                 requestId,
-                                lastFrameNumber);
+                                requestLastFrameNumbers.getLastFrameNumber());
                         }
                     }
                 };
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 36fc4f9..50eed3e 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -173,6 +173,27 @@
                 "ro.build.version.sdk", 0);
 
         /**
+         * The developer preview revision of a prerelease SDK. This value will always
+         * be <code>0</code> on production platform builds/devices.
+         *
+         * <p>When this value is nonzero, any new API added since the last
+         * officially published {@link #SDK_INT API level} is only guaranteed to be present
+         * on that specific preview revision. For example, an API <code>Activity.fooBar()</code>
+         * might be present in preview revision 1 but renamed or removed entirely in
+         * preview revision 2, which may cause an app attempting to call it to crash
+         * at runtime.</p>
+         *
+         * <p>Experimental apps targeting preview APIs should check this value for
+         * equality (<code>==</code>) with the preview SDK revision they were built for
+         * before using any prerelease platform APIs. Apps that detect a preview SDK revision
+         * other than the specific one they expect should fall back to using APIs from
+         * the previously published API level only to avoid unwanted runtime exceptions.
+         * </p>
+         */
+        public static final int PREVIEW_SDK_INT = SystemProperties.getInt(
+                "ro.build.version.preview_sdk", 0);
+
+        /**
          * The current development codename, or the string "REL" if this is
          * a release build.
          */
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 4aff7a1..19c8fa9 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -169,6 +169,65 @@
         public int otherSwappedOut;
 
         /** @hide */
+        public static final int HEAP_UNKNOWN = 0;
+        /** @hide */
+        public static final int HEAP_DALVIK = 1;
+        /** @hide */
+        public static final int HEAP_NATIVE = 2;
+
+        /** @hide */
+        public static final int OTHER_DALVIK_OTHER = 0;
+        /** @hide */
+        public static final int OTHER_STACK = 1;
+        /** @hide */
+        public static final int OTHER_CURSOR = 2;
+        /** @hide */
+        public static final int OTHER_ASHMEM = 3;
+        /** @hide */
+        public static final int OTHER_GL_DEV = 4;
+        /** @hide */
+        public static final int OTHER_UNKNOWN_DEV = 5;
+        /** @hide */
+        public static final int OTHER_SO = 6;
+        /** @hide */
+        public static final int OTHER_JAR = 7;
+        /** @hide */
+        public static final int OTHER_APK = 8;
+        /** @hide */
+        public static final int OTHER_TTF = 9;
+        /** @hide */
+        public static final int OTHER_DEX = 10;
+        /** @hide */
+        public static final int OTHER_OAT = 11;
+        /** @hide */
+        public static final int OTHER_ART = 12;
+        /** @hide */
+        public static final int OTHER_UNKNOWN_MAP = 13;
+        /** @hide */
+        public static final int OTHER_GRAPHICS = 14;
+        /** @hide */
+        public static final int OTHER_GL = 15;
+        /** @hide */
+        public static final int OTHER_OTHER_MEMTRACK = 16;
+
+        /** @hide */
+        public static final int OTHER_DALVIK_NORMAL = 17;
+        /** @hide */
+        public static final int OTHER_DALVIK_LARGE = 18;
+        /** @hide */
+        public static final int OTHER_DALVIK_LINEARALLOC = 19;
+        /** @hide */
+        public static final int OTHER_DALVIK_ACCOUNTING = 20;
+        /** @hide */
+        public static final int OTHER_DALVIK_CODE_CACHE = 21;
+        /** @hide */
+        public static final int OTHER_DALVIK_ZYGOTE = 22;
+        /** @hide */
+        public static final int OTHER_DALVIK_NON_MOVING = 23;
+        /** @hide */
+        public static final int OTHER_DALVIK_INDIRECT_REFERENCE_TABLE = 24;
+
+        /** @hide */
         public static final int NUM_OTHER_STATS = 17;
 
         /** @hide */
@@ -284,6 +343,11 @@
         }
 
         /** @hide */
+        public int getOtherPrivate(int which) {
+          return getOtherPrivateClean(which) + getOtherPrivateDirty(which);
+        }
+
+        /** @hide */
         public int getOtherSharedClean(int which) {
             return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
         }
@@ -296,35 +360,157 @@
         /** @hide */
         public static String getOtherLabel(int which) {
             switch (which) {
-                case 0: return "Dalvik Other";
-                case 1: return "Stack";
-                case 2: return "Cursor";
-                case 3: return "Ashmem";
-                case 4: return "Gfx dev";
-                case 5: return "Other dev";
-                case 6: return ".so mmap";
-                case 7: return ".jar mmap";
-                case 8: return ".apk mmap";
-                case 9: return ".ttf mmap";
-                case 10: return ".dex mmap";
-                case 11: return ".oat mmap";
-                case 12: return ".art mmap";
-                case 13: return "Other mmap";
-                case 14: return "EGL mtrack";
-                case 15: return "GL mtrack";
-                case 16: return "Other mtrack";
-                case 17: return ".Heap";
-                case 18: return ".LOS";
-                case 19: return ".LinearAlloc";
-                case 20: return ".GC";
-                case 21: return ".JITCache";
-                case 22: return ".Zygote";
-                case 23: return ".NonMoving";
-                case 24: return ".IndirectRef";
+                case OTHER_DALVIK_OTHER: return "Dalvik Other";
+                case OTHER_STACK: return "Stack";
+                case OTHER_CURSOR: return "Cursor";
+                case OTHER_ASHMEM: return "Ashmem";
+                case OTHER_GL_DEV: return "Gfx dev";
+                case OTHER_UNKNOWN_DEV: return "Other dev";
+                case OTHER_SO: return ".so mmap";
+                case OTHER_JAR: return ".jar mmap";
+                case OTHER_APK: return ".apk mmap";
+                case OTHER_TTF: return ".ttf mmap";
+                case OTHER_DEX: return ".dex mmap";
+                case OTHER_OAT: return ".oat mmap";
+                case OTHER_ART: return ".art mmap";
+                case OTHER_UNKNOWN_MAP: return "Other mmap";
+                case OTHER_GRAPHICS: return "EGL mtrack";
+                case OTHER_GL: return "GL mtrack";
+                case OTHER_OTHER_MEMTRACK: return "Other mtrack";
+                case OTHER_DALVIK_NORMAL: return ".Heap";
+                case OTHER_DALVIK_LARGE: return ".LOS";
+                case OTHER_DALVIK_LINEARALLOC: return ".LinearAlloc";
+                case OTHER_DALVIK_ACCOUNTING: return ".GC";
+                case OTHER_DALVIK_CODE_CACHE: return ".JITCache";
+                case OTHER_DALVIK_ZYGOTE: return ".Zygote";
+                case OTHER_DALVIK_NON_MOVING: return ".NonMoving";
+                case OTHER_DALVIK_INDIRECT_REFERENCE_TABLE: return ".IndirectRef";
                 default: return "????";
             }
         }
 
+        /**
+         * Pss of Java Heap bytes in KB due to the application.
+         * Notes:
+         *  * OTHER_ART is the boot image. Anything private here is blamed on
+         *    the application, not the system.
+         *  * dalvikPrivateDirty includes private zygote, which means the
+         *    application dirtied something allocated by the zygote. We blame
+         *    the application for that memory, not the system.
+         *  * Does not include OTHER_DALVIK_OTHER, which is considered VM
+         *    Overhead and lumped into Private Other.
+         *  * We don't include dalvikPrivateClean, because there should be no
+         *    such thing as private clean for the Java Heap.
+         * @hide
+         */
+        public int getSummaryJavaHeap() {
+            return dalvikPrivateDirty + getOtherPrivate(OTHER_ART);
+        }
+
+        /**
+         * Pss of Native Heap bytes in KB due to the application.
+         * Notes:
+         *  * Includes private dirty malloc space.
+         *  * We don't include nativePrivateClean, because there should be no
+         *    such thing as private clean for the Native Heap.
+         * @hide
+         */
+        public int getSummaryNativeHeap() {
+            return nativePrivateDirty;
+        }
+
+        /**
+         * Pss of code and other static resource bytes in KB due to
+         * the application.
+         * @hide
+         */
+        public int getSummaryCode() {
+            return getOtherPrivate(OTHER_SO)
+              + getOtherPrivate(OTHER_JAR)
+              + getOtherPrivate(OTHER_APK)
+              + getOtherPrivate(OTHER_TTF)
+              + getOtherPrivate(OTHER_DEX)
+              + getOtherPrivate(OTHER_OAT);
+        }
+
+        /**
+         * Pss in KB of the stack due to the application.
+         * Notes:
+         *  * Includes private dirty stack, which includes both Java and Native
+         *    stack.
+         *  * Does not include private clean stack, because there should be no
+         *    such thing as private clean for the stack.
+         * @hide
+         */
+        public int getSummaryStack() {
+            return getOtherPrivateDirty(OTHER_STACK);
+        }
+
+        /**
+         * Pss in KB of graphics due to the application.
+         * Notes:
+         *  * Includes private Gfx, EGL, and GL.
+         *  * Warning: These numbers can be misreported by the graphics drivers.
+         *  * We don't include shared graphics. It may make sense to, because
+         *    shared graphics are likely buffers due to the application
+         *    anyway, but it's simpler to implement to just group all shared
+         *    memory into the System category.
+         * @hide
+         */
+        public int getSummaryGraphics() {
+            return getOtherPrivate(OTHER_GL_DEV)
+              + getOtherPrivate(OTHER_GRAPHICS)
+              + getOtherPrivate(OTHER_GL);
+        }
+
+        /**
+         * Pss in KB due to the application that haven't otherwise been
+         * accounted for.
+         * @hide
+         */
+        public int getSummaryPrivateOther() {
+            return getTotalPrivateClean()
+              + getTotalPrivateDirty()
+              - getSummaryJavaHeap()
+              - getSummaryNativeHeap()
+              - getSummaryCode()
+              - getSummaryStack()
+              - getSummaryGraphics();
+        }
+
+        /**
+         * Pss in KB due to the system.
+         * Notes:
+         *  * Includes all shared memory.
+         * @hide
+         */
+        public int getSummarySystem() {
+            return getTotalPss()
+              - getTotalPrivateClean()
+              - getTotalPrivateDirty();
+        }
+
+        /**
+         * Total Pss in KB.
+         * @hide
+         */
+        public int getSummaryTotalPss() {
+            return getTotalPss();
+        }
+
+        /**
+         * Total Swap in KB.
+         * Notes:
+         *  * Some of this memory belongs in other categories, but we don't
+         *    know if the Swap memory is shared or private, so we don't know
+         *    what to blame on the application and what on the system.
+         *    For now, just lump all the Swap in one place.
+         * @hide
+         */
+        public int getSummaryTotalSwap() {
+            return getTotalSwappedOut();
+        }
+
         public int describeContents() {
             return 0;
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a7af838..7c3c11b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6156,6 +6156,17 @@
         */
        public static final String MOBILE_DATA = "mobile_data";
 
+       /**
+        * Whether the mobile data connection should remain active even when higher
+        * priority networks like WiFi are active, to help make network switching faster.
+        *
+        * See ConnectivityService for more info.
+        *
+        * (0 = disabled, 1 = enabled)
+        * @hide
+        */
+       public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
+
        /** {@hide} */
        public static final String NETSTATS_ENABLED = "netstats_enabled";
        /** {@hide} */
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 11226a9..c4dc5ed 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -95,6 +95,45 @@
         } while (true);
     }
 
+    /** {@inheritDoc} */
+    public boolean isBoundary(int offset) {
+        int shiftedOffset = offset - mOffsetShift;
+        checkOffsetIsValid(shiftedOffset);
+        return mIterator.isBoundary(shiftedOffset);
+    }
+
+    /**
+     * Returns the position of next boundary after the given offset. Returns
+     * {@code DONE} if there is no boundary after the given offset.
+     *
+     * @param offset the given start position to search from.
+     * @return the position of the last boundary preceding the given offset.
+     */
+    public int nextBoundary(int offset) {
+        int shiftedOffset = offset - mOffsetShift;
+        shiftedOffset = mIterator.following(shiftedOffset);
+        if (shiftedOffset == BreakIterator.DONE) {
+            return BreakIterator.DONE;
+        }
+        return shiftedOffset + mOffsetShift;
+    }
+
+    /**
+     * Returns the position of boundary preceding the given offset or
+     * {@code DONE} if the given offset specifies the starting position.
+     *
+     * @param offset the given start position to search from.
+     * @return the position of the last boundary preceding the given offset.
+     */
+    public int prevBoundary(int offset) {
+        int shiftedOffset = offset - mOffsetShift;
+        shiftedOffset = mIterator.preceding(shiftedOffset);
+        if (shiftedOffset == BreakIterator.DONE) {
+            return BreakIterator.DONE;
+        }
+        return shiftedOffset + mOffsetShift;
+    }
+
     /** If <code>offset</code> is within a word, returns the index of the first character of that
      * word, otherwise returns BreakIterator.DONE.
      *
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index ebc2aac..1b25505 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1639,6 +1639,7 @@
         for (int i = 0; i < count; i++) {
             TransitionValues values = lookIn.get(i);
             if (values == null) {
+                // Null values are always added to the end of the list, so we know to stop now.
                 return null;
             }
             if (values.view == view) {
@@ -1742,6 +1743,9 @@
                     View oldView = oldInfo.view;
                     TransitionValues startValues = getTransitionValues(oldView, true);
                     TransitionValues endValues = getMatchedTransitionValues(oldView, true);
+                    if (startValues == null && endValues == null) {
+                        endValues = mEndValues.viewValues.get(oldView);
+                    }
                     boolean cancel = (startValues != null || endValues != null) &&
                             oldInfo.transition.areValuesChanged(oldValues, endValues);
                     if (cancel) {
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 9047b1d..ce50091 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -87,9 +87,12 @@
         }
     }
     
-    @Override public void setTheme(int resid) {
-        mThemeResource = resid;
-        initializeTheme();
+    @Override
+    public void setTheme(int resid) {
+        if (mThemeResource != resid) {
+            mThemeResource = resid;
+            initializeTheme();
+        }
     }
     
     /** @hide */
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index 9f46f45..41502b6 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -82,8 +82,7 @@
             mView.mGhostView = null;
             final ViewGroup parent = (ViewGroup) mView.getParent();
             if (parent != null) {
-                parent.mRecreateDisplayList = true;
-                parent.updateDisplayListIfDirty();
+                parent.invalidate();
             }
         }
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f62e6a2..e1f1816 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -633,7 +633,6 @@
  * </p>
  *
  * @attr ref android.R.styleable#View_alpha
- * @attr ref android.R.styleable#View_assistBlocked
  * @attr ref android.R.styleable#View_background
  * @attr ref android.R.styleable#View_clickable
  * @attr ref android.R.styleable#View_contentDescription
@@ -2533,7 +2532,7 @@
             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
 
     /**
-     * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse
+     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
      * into this view.<p>
      */
     static final int PFLAG3_ASSIST_BLOCKED = 0x100;
@@ -4050,11 +4049,6 @@
                         viewFlagMasks |= SAVE_DISABLED_MASK;
                     }
                     break;
-                case com.android.internal.R.styleable.View_assistBlocked:
-                    if (a.getBoolean(attr, false)) {
-                        mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
-                    }
-                    break;
                 case com.android.internal.R.styleable.View_duplicateParentState:
                     if (a.getBoolean(attr, false)) {
                         viewFlagValues |= DUPLICATE_PARENT_STATE;
@@ -6163,7 +6157,7 @@
      * @param structure Fill in with structured view data.  The default implementation
      * fills in all data that can be inferred from the view itself.
      */
-    public void onProvideAssistStructure(ViewAssistStructure structure) {
+    public void onProvideStructure(ViewStructure structure) {
         final int id = mID;
         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
                 && (id&0x0000ffff) != 0) {
@@ -6217,6 +6211,11 @@
         structure.setContentDescription(getContentDescription());
     }
 
+    /** @hide */
+    public void onProvideAssistStructure(ViewStructure structure) {
+        onProvideStructure(structure);
+    }
+
     /**
      * Called when assist structure is being retrieved from a view as part of
      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
@@ -6225,19 +6224,24 @@
      * view's virtual accessibility nodes, if any.  You can override this for a more
      * optimal implementation providing this data.
      */
-    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
+    public void onProvideVirtualStructure(ViewStructure structure) {
         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
         if (provider != null) {
             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
             Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
             structure.setChildCount(1);
-            ViewAssistStructure root = structure.newChild(0);
-            populateVirtualAssistStructure(root, provider, info);
+            ViewStructure root = structure.newChild(0);
+            populateVirtualStructure(root, provider, info);
             info.recycle();
         }
     }
 
-    private void populateVirtualAssistStructure(ViewAssistStructure structure,
+    /** @hide */
+    public void onProvideVirtualAssistStructure(ViewStructure structure) {
+        onProvideVirtualStructure(structure);
+    }
+
+    private void populateVirtualStructure(ViewStructure structure,
             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
                 null, null, null);
@@ -6288,19 +6292,19 @@
             for (int i=0; i<NCHILDREN; i++) {
                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
-                ViewAssistStructure child = structure.newChild(i);
-                populateVirtualAssistStructure(child, provider, cinfo);
+                ViewStructure child = structure.newChild(i);
+                populateVirtualStructure(child, provider, cinfo);
                 cinfo.recycle();
             }
         }
     }
 
     /**
-     * Dispatch creation of {@link ViewAssistStructure} down the hierarchy.  The default
-     * implementation calls {@link #onProvideAssistStructure} and
-     * {@link #onProvideVirtualAssistStructure}.
+     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
+     * implementation calls {@link #onProvideStructure} and
+     * {@link #onProvideVirtualStructure}.
      */
-    public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
+    public void dispatchProvideStructure(ViewStructure structure) {
         if (!isAssistBlocked()) {
             onProvideAssistStructure(structure);
             onProvideVirtualAssistStructure(structure);
@@ -7904,8 +7908,9 @@
     }
 
     /**
+     * @hide
      * Indicates whether this view will participate in data collection through
-     * {@link android.view.ViewAssistStructure}.  If true, it will not provide any data
+     * {@link ViewStructure}.  If true, it will not provide any data
      * for itself or its children.  If false, the normal data collection will be allowed.
      *
      * @return Returns false if assist data collection is not blocked, else true.
@@ -7918,17 +7923,18 @@
     }
 
     /**
+     * @hide
      * Controls whether assist data collection from this view and its children is enabled
-     * (that is, whether {@link #onProvideAssistStructure} and
-     * {@link #onProvideVirtualAssistStructure} will be called).  The default value is false,
+     * (that is, whether {@link #onProvideStructure} and
+     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
      * allowing normal assist collection.  Setting this to false will disable assist collection.
      *
      * @param enabled Set to true to <em>disable</em> assist data collection, or false
      * (the default) to allow it.
      *
      * @see #isAssistBlocked()
-     * @see #onProvideAssistStructure
-     * @see #onProvideVirtualAssistStructure
+     * @see #onProvideStructure
+     * @see #onProvideVirtualStructure
      * @attr ref android.R.styleable#View_assistBlocked
      */
     public void setAssistBlocked(boolean enabled) {
@@ -22353,4 +22359,138 @@
         final String output = bits + " " + name;
         found.put(key, output);
     }
+
+    /** {@hide} */
+    public void encode(@NonNull ViewHierarchyEncoder stream) {
+        stream.beginObject(this);
+        encodeProperties(stream);
+        stream.endObject();
+    }
+
+    /** {@hide} */
+    @CallSuper
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        Object resolveId = ViewDebug.resolveId(getContext(), mID);
+        if (resolveId instanceof String) {
+            stream.addProperty("id", (String) resolveId);
+        } else {
+            stream.addProperty("id", mID);
+        }
+
+        stream.addProperty("misc:transformation.alpha",
+                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
+        stream.addProperty("misc:transitionName", getTransitionName());
+
+        // layout
+        stream.addProperty("layout:left", mLeft);
+        stream.addProperty("layout:right", mRight);
+        stream.addProperty("layout:top", mTop);
+        stream.addProperty("layout:bottom", mBottom);
+        stream.addProperty("layout:width", getWidth());
+        stream.addProperty("layout:height", getHeight());
+        stream.addProperty("layout:layoutDirection", getLayoutDirection());
+        stream.addProperty("layout:layoutRtl", isLayoutRtl());
+        stream.addProperty("layout:hasTransientState", hasTransientState());
+        stream.addProperty("layout:baseline", getBaseline());
+
+        // layout params
+        ViewGroup.LayoutParams layoutParams = getLayoutParams();
+        if (layoutParams != null) {
+            stream.addPropertyKey("layoutParams");
+            layoutParams.encode(stream);
+        }
+
+        // scrolling
+        stream.addProperty("scrolling:scrollX", mScrollX);
+        stream.addProperty("scrolling:scrollY", mScrollY);
+
+        // padding
+        stream.addProperty("padding:paddingLeft", mPaddingLeft);
+        stream.addProperty("padding:paddingRight", mPaddingRight);
+        stream.addProperty("padding:paddingTop", mPaddingTop);
+        stream.addProperty("padding:paddingBottom", mPaddingBottom);
+        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
+        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
+        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
+        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
+        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
+
+        // measurement
+        stream.addProperty("measurement:minHeight", mMinHeight);
+        stream.addProperty("measurement:minWidth", mMinWidth);
+        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
+        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
+
+        // drawing
+        stream.addProperty("drawing:elevation", getElevation());
+        stream.addProperty("drawing:translationX", getTranslationX());
+        stream.addProperty("drawing:translationY", getTranslationY());
+        stream.addProperty("drawing:translationZ", getTranslationZ());
+        stream.addProperty("drawing:rotation", getRotation());
+        stream.addProperty("drawing:rotationX", getRotationX());
+        stream.addProperty("drawing:rotationY", getRotationY());
+        stream.addProperty("drawing:scaleX", getScaleX());
+        stream.addProperty("drawing:scaleY", getScaleY());
+        stream.addProperty("drawing:pivotX", getPivotX());
+        stream.addProperty("drawing:pivotY", getPivotY());
+        stream.addProperty("drawing:opaque", isOpaque());
+        stream.addProperty("drawing:alpha", getAlpha());
+        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
+        stream.addProperty("drawing:shadow", hasShadow());
+        stream.addProperty("drawing:solidColor", getSolidColor());
+        stream.addProperty("drawing:layerType", mLayerType);
+        stream.addProperty("drawing:willNotDraw", willNotDraw());
+        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
+        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
+        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
+        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
+
+        // focus
+        stream.addProperty("focus:hasFocus", hasFocus());
+        stream.addProperty("focus:isFocused", isFocused());
+        stream.addProperty("focus:isFocusable", isFocusable());
+        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
+
+        stream.addProperty("misc:clickable", isClickable());
+        stream.addProperty("misc:pressed", isPressed());
+        stream.addProperty("misc:selected", isSelected());
+        stream.addProperty("misc:touchMode", isInTouchMode());
+        stream.addProperty("misc:hovered", isHovered());
+        stream.addProperty("misc:activated", isActivated());
+
+        stream.addProperty("misc:visibility", getVisibility());
+        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
+        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
+
+        stream.addProperty("misc:enabled", isEnabled());
+        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
+        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
+
+        // theme attributes
+        Resources.Theme theme = getContext().getTheme();
+        if (theme != null) {
+            stream.addPropertyKey("theme");
+            theme.encode(stream);
+        }
+
+        // view attribute information
+        int n = mAttributes != null ? mAttributes.length : 0;
+        stream.addProperty("meta:__attrCount__", n/2);
+        for (int i = 0; i < n; i += 2) {
+            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
+        }
+
+        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
+
+        // text
+        stream.addProperty("text:textDirection", getTextDirection());
+        stream.addProperty("text:textAlignment", getTextAlignment());
+
+        // accessibility
+        CharSequence contentDescription = getContentDescription();
+        stream.addProperty("accessibility:contentDescription",
+                contentDescription == null ? "" : contentDescription.toString());
+        stream.addProperty("accessibility:labelFor", getLabelFor());
+        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
+    }
 }
diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java
index fccfbb8..a66d93c 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/android/view/ViewAssistStructure.java
@@ -16,70 +16,9 @@
 
 package android.view;
 
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.text.TextPaint;
-
 /**
- * Container for storing additional per-view data generated by {@link View#onProvideAssistStructure
- * View.onProvideAssistStructure}.
+ * @deprecated Temporary until old apps can move off this.
  */
-public abstract class ViewAssistStructure {
-    public abstract void setId(int id, String packageName, String typeName, String entryName);
-
-    public abstract void setDimens(int left, int top, int scrollX, int scrollY, int width,
-            int height);
-
-    public abstract void setVisibility(int visibility);
-
-    public abstract void setAssistBlocked(boolean state);
-
-    public abstract void setEnabled(boolean state);
-
-    public abstract void setClickable(boolean state);
-
-    public abstract void setLongClickable(boolean state);
-
-    public abstract void setStylusButtonPressable(boolean state);
-
-    public abstract void setFocusable(boolean state);
-
-    public abstract void setFocused(boolean state);
-
-    public abstract void setAccessibilityFocused(boolean state);
-
-    public abstract void setCheckable(boolean state);
-
-    public abstract void setChecked(boolean state);
-
-    public abstract void setSelected(boolean state);
-
-    public abstract void setActivated(boolean state);
-
-    public abstract void setClassName(String className);
-
-    public abstract void setContentDescription(CharSequence contentDescription);
-
-    public abstract void setText(CharSequence text);
-    public abstract void setText(CharSequence text, int selectionStart, int selectionEnd);
-    public abstract void setTextPaint(TextPaint paint);
-    public abstract void setHint(CharSequence hint);
-
-    public abstract CharSequence getText();
-    public abstract int getTextSelectionStart();
-    public abstract int getTextSelectionEnd();
-    public abstract CharSequence getHint();
-
-    public abstract Bundle editExtras();
-    public abstract void clearExtras();
-
-    public abstract void setChildCount(int num);
-    public abstract int getChildCount();
-    public abstract ViewAssistStructure newChild(int index);
-
-    public abstract ViewAssistStructure asyncNewChild(int index);
-    public abstract void asyncCommit();
-
-    /** @hide */
-    public abstract Rect getTempRect();
+@Deprecated
+public abstract class ViewAssistStructure extends ViewStructure {
 }
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 27304f5..8bf53a8 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -800,6 +801,7 @@
 
     /**
      * Dumps the view hierarchy starting from the given view.
+     * @deprecated See {@link #dumpv2(View, ByteArrayOutputStream)} below.
      * @hide
      */
     public static void dump(View root, boolean skipChildren, boolean includeProperties,
@@ -825,6 +827,28 @@
     }
 
     /**
+     * Dumps the view hierarchy starting from the given view.
+     * Rather than using reflection, it uses View's encode method to obtain all the properties.
+     * @hide
+     */
+    public static void dumpv2(@NonNull final View view, @NonNull ByteArrayOutputStream out)
+            throws InterruptedException {
+        final ViewHierarchyEncoder encoder = new ViewHierarchyEncoder(out);
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        view.post(new Runnable() {
+            @Override
+            public void run() {
+                view.encode(encoder);
+                latch.countDown();
+            }
+        });
+
+        latch.await(2, TimeUnit.SECONDS);
+        encoder.endStream();
+    }
+
+    /**
      * Dumps the theme attributes from the given View.
      * @hide
      */
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index babb4e9..51c4760 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2878,12 +2878,12 @@
     }
 
     /**
-     * Dispatch creation of {@link ViewAssistStructure} down the hierarchy.  This implementation
+     * Dispatch creation of {@link ViewStructure} down the hierarchy.  This implementation
      * adds in all child views of the view group, in addition to calling the default View
      * implementation.
      */
-    public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
-        super.dispatchProvideAssistStructure(structure);
+    public void dispatchProvideStructure(ViewStructure structure) {
+        super.dispatchProvideStructure(structure);
         if (!isAssistBlocked()) {
             if (structure.getChildCount() == 0) {
                 final int childrenCount = getChildCount();
@@ -2898,8 +2898,8 @@
                                 ? getChildDrawingOrder(childrenCount, i) : i;
                         final View child = (preorderedList == null)
                                 ? children[childIndex] : preorderedList.get(childIndex);
-                        ViewAssistStructure cstructure = structure.newChild(i);
-                        child.dispatchProvideAssistStructure(cstructure);
+                        ViewStructure cstructure = structure.newChild(i);
+                        child.dispatchProvideStructure(cstructure);
                     }
                 }
             }
@@ -6861,6 +6861,19 @@
             }
             return String.valueOf(size);
         }
+
+        /** @hide */
+        void encode(@NonNull ViewHierarchyEncoder encoder) {
+            encoder.beginObject(this);
+            encodeProperties(encoder);
+            encoder.endObject();
+        }
+
+        /** @hide */
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            encoder.addProperty("width", width);
+            encoder.addProperty("height", height);
+        }
     }
 
     /**
@@ -7329,6 +7342,18 @@
                     bottomMargin,
                     paint);
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+            encoder.addProperty("leftMargin", leftMargin);
+            encoder.addProperty("topMargin", topMargin);
+            encoder.addProperty("rightMargin", rightMargin);
+            encoder.addProperty("bottomMargin", bottomMargin);
+            encoder.addProperty("startMargin", startMargin);
+            encoder.addProperty("endMargin", endMargin);
+        }
     }
 
     /* Describes a touched view and the ids of the pointers that it has captured.
@@ -7665,4 +7690,23 @@
 
         canvas.drawLines(sDebugLines, paint);
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+
+        encoder.addProperty("focus:descendantFocusability", getDescendantFocusability());
+        encoder.addProperty("drawing:clipChildren", getClipChildren());
+        encoder.addProperty("drawing:clipToPadding", getClipToPadding());
+        encoder.addProperty("drawing:childrenDrawingOrderEnabled", isChildrenDrawingOrderEnabled());
+        encoder.addProperty("drawing:persistentDrawingCache", getPersistentDrawingCache());
+
+        int n = getChildCount();
+        encoder.addProperty("meta:__childCount__", (short)n);
+        for (int i = 0; i < n; i++) {
+            encoder.addPropertyKey("meta:__child__" + i);
+            getChildAt(i).encode(encoder);
+        }
+    }
 }
diff --git a/core/java/android/view/ViewHierarchyEncoder.java b/core/java/android/view/ViewHierarchyEncoder.java
new file mode 100644
index 0000000..8770216
--- /dev/null
+++ b/core/java/android/view/ViewHierarchyEncoder.java
@@ -0,0 +1,201 @@
+package android.view;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@link ViewHierarchyEncoder} is a serializer that is tailored towards writing out
+ * view hierarchies (the view tree, along with the properties for each view) to a stream.
+ *
+ * It is typically used as follows:
+ * <pre>
+ *   ViewHierarchyEncoder e = new ViewHierarchyEncoder();
+ *
+ *   for (View view : views) {
+ *      e.beginObject(view);
+ *      e.addProperty("prop1", value);
+ *      ...
+ *      e.endObject();
+ *   }
+ *
+ *   // repeat above snippet for each view, finally end with:
+ *   e.endStream();
+ * </pre>
+ *
+ * <p>On the stream, a snippet such as the above gets encoded as a series of Map's (one
+ * corresponding to each view) with the property name as the key and the property value
+ * as the value.
+ *
+ * <p>Since the property names are practically the same across all views, rather than using
+ * the property name directly as the key, we use a short integer id corresponding to each
+ * property name as the key. A final map is added at the end which contains the mapping
+ * from the integer to its property name.
+ *
+ * <p>A value is encoded as a single byte type identifier followed by the encoding of the
+ * value. Only primitive types are supported as values, in addition to the Map type.
+ *
+ * @hide
+ */
+public class ViewHierarchyEncoder {
+    // Prefixes for simple primitives. These match the JNI definitions.
+    private static final byte SIG_BOOLEAN = 'Z';
+    private static final byte SIG_BYTE = 'B';
+    private static final byte SIG_SHORT = 'S';
+    private static final byte SIG_INT = 'I';
+    private static final byte SIG_LONG = 'J';
+    private static final byte SIG_FLOAT = 'F';
+    private static final byte SIG_DOUBLE = 'D';
+
+    // Prefixes for some commonly used objects
+    private static final byte SIG_STRING = 'R';
+
+    private static final byte SIG_MAP = 'M'; // a map with an short key
+    private static final short SIG_END_MAP = 0;
+
+    private final DataOutputStream mStream;
+
+    private final Map<String,Short> mPropertyNames = new HashMap<String, Short>(200);
+    private short mPropertyId = 1;
+    private Charset mCharset = Charset.forName("utf-8");
+
+    public ViewHierarchyEncoder(@NonNull ByteArrayOutputStream stream) {
+        mStream = new DataOutputStream(stream);
+    }
+
+    public void beginObject(@NonNull Object o) {
+        startPropertyMap();
+        addProperty("meta:__name__", o.getClass().getName());
+        addProperty("meta:__hash__", o.hashCode());
+    }
+
+    public void endObject() {
+        endPropertyMap();
+    }
+
+    public void endStream() {
+        // write out the string table
+        startPropertyMap();
+        addProperty("__name__", "propertyIndex");
+        for (Map.Entry<String,Short> entry : mPropertyNames.entrySet()) {
+            writeShort(entry.getValue());
+            writeString(entry.getKey());
+        }
+        endPropertyMap();
+    }
+
+    public void addProperty(@NonNull String name, boolean v) {
+        writeShort(createPropertyIndex(name));
+        writeBoolean(v);
+    }
+
+    public void addProperty(@NonNull String name, short s) {
+        writeShort(createPropertyIndex(name));
+        writeShort(s);
+    }
+
+    public void addProperty(@NonNull String name, int v) {
+        writeShort(createPropertyIndex(name));
+        writeInt(v);
+    }
+
+    public void addProperty(@NonNull String name, float v) {
+        writeShort(createPropertyIndex(name));
+        writeFloat(v);
+    }
+
+    public void addProperty(@NonNull String name, @Nullable String s) {
+        writeShort(createPropertyIndex(name));
+        writeString(s);
+    }
+
+    /**
+     * Writes the given name as the property name, and leaves it to the callee
+     * to fill in value for this property.
+     */
+    public void addPropertyKey(@NonNull String name) {
+        writeShort(createPropertyIndex(name));
+    }
+
+    private short createPropertyIndex(@NonNull String name) {
+        Short index = mPropertyNames.get(name);
+        if (index == null) {
+            index = mPropertyId++;
+            mPropertyNames.put(name, index);
+        }
+
+        return index;
+    }
+
+    private void startPropertyMap() {
+        try {
+            mStream.write(SIG_MAP);
+        } catch (IOException e) {
+            // does not happen since the stream simply wraps a ByteArrayOutputStream
+        }
+    }
+
+    private void endPropertyMap() {
+        writeShort(SIG_END_MAP);
+    }
+
+    private void writeBoolean(boolean v) {
+        try {
+            mStream.write(SIG_BOOLEAN);
+            mStream.write(v ? 1 : 0);
+        } catch (IOException e) {
+            // does not happen since the stream simply wraps a ByteArrayOutputStream
+        }
+    }
+
+    private void writeShort(short s) {
+        try {
+            mStream.write(SIG_SHORT);
+            mStream.writeShort(s);
+        } catch (IOException e) {
+            // does not happen since the stream simply wraps a ByteArrayOutputStream
+        }
+    }
+
+    private void writeInt(int i) {
+        try {
+            mStream.write(SIG_INT);
+            mStream.writeInt(i);
+        } catch (IOException e) {
+            // does not happen since the stream simply wraps a ByteArrayOutputStream
+        }
+    }
+
+    private void writeFloat(float v) {
+        try {
+            mStream.write(SIG_FLOAT);
+            mStream.writeFloat(v);
+        } catch (IOException e) {
+            // does not happen since the stream simply wraps a ByteArrayOutputStream
+        }
+    }
+
+    private void writeString(@Nullable String s) {
+        if (s == null) {
+            s = "";
+        }
+
+        try {
+            mStream.write(SIG_STRING);
+            byte[] bytes = s.getBytes(mCharset);
+
+            short len = (short)Math.min(bytes.length, Short.MAX_VALUE);
+            mStream.writeShort(len);
+
+            mStream.write(bytes, 0, len);
+        } catch (IOException e) {
+            // does not happen since the stream simply wraps a ByteArrayOutputStream
+        }
+    }
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c9c2a82..ea1dadb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -654,6 +654,10 @@
         return (mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
     }
 
+    public int getWindowFlags() {
+        return mWindowAttributes.flags;
+    }
+
     public CharSequence getTitle() {
         return mWindowAttributes.getTitle();
     }
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
new file mode 100644
index 0000000..8dc49ac
--- /dev/null
+++ b/core/java/android/view/ViewStructure.java
@@ -0,0 +1,86 @@
+/*
+ * 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.view;
+
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.text.TextPaint;
+
+/**
+ * Container for storing additional per-view data generated by {@link View#onProvideStructure
+ * View.onProvideStructure}.
+ */
+public abstract class ViewStructure {
+    public abstract void setId(int id, String packageName, String typeName, String entryName);
+
+    public abstract void setDimens(int left, int top, int scrollX, int scrollY, int width,
+            int height);
+
+    public abstract void setVisibility(int visibility);
+
+    /** @hide */
+    public abstract void setAssistBlocked(boolean state);
+
+    public abstract void setEnabled(boolean state);
+
+    public abstract void setClickable(boolean state);
+
+    public abstract void setLongClickable(boolean state);
+
+    public abstract void setStylusButtonPressable(boolean state);
+
+    public abstract void setFocusable(boolean state);
+
+    public abstract void setFocused(boolean state);
+
+    public abstract void setAccessibilityFocused(boolean state);
+
+    public abstract void setCheckable(boolean state);
+
+    public abstract void setChecked(boolean state);
+
+    public abstract void setSelected(boolean state);
+
+    public abstract void setActivated(boolean state);
+
+    public abstract void setClassName(String className);
+
+    public abstract void setContentDescription(CharSequence contentDescription);
+
+    public abstract void setText(CharSequence text);
+    public abstract void setText(CharSequence text, int selectionStart, int selectionEnd);
+    public abstract void setTextPaint(TextPaint paint);
+    public abstract void setHint(CharSequence hint);
+
+    public abstract CharSequence getText();
+    public abstract int getTextSelectionStart();
+    public abstract int getTextSelectionEnd();
+    public abstract CharSequence getHint();
+
+    public abstract Bundle getExtras();
+    public abstract boolean hasExtras();
+
+    public abstract void setChildCount(int num);
+    public abstract int getChildCount();
+    public abstract ViewAssistStructure newChild(int index);
+
+    public abstract ViewAssistStructure asyncNewChild(int index);
+    public abstract void asyncCommit();
+
+    /** @hide */
+    public abstract Rect getTempRect();
+}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e983910..2797b6e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -16,11 +16,11 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Presentation;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
-import android.graphics.Insets;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.IBinder;
@@ -1119,6 +1119,15 @@
         public static final int PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS = 0x00000800;
 
         /**
+         * Flag to force the status bar window to be visible all the time. If the bar is hidden when
+         * this flag is set it will be shown again and the bar will have a transparent background.
+         * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}.
+         *
+         * {@hide}
+         */
+        public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
@@ -2066,5 +2075,18 @@
         }
 
         private CharSequence mTitle = "";
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+
+            encoder.addProperty("x", x);
+            encoder.addProperty("y", y);
+            encoder.addProperty("horizontalWeight", horizontalWeight);
+            encoder.addProperty("verticalWeight", verticalWeight);
+            encoder.addProperty("type", type);
+            encoder.addProperty("flags", flags);
+        }
     }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7ab5aaa..e27e253 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.Widget;
 import android.content.Context;
@@ -40,9 +41,10 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewAssistStructure;
+import android.view.ViewStructure;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -2426,7 +2428,7 @@
     }
 
     @Override
-    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
+    public void onProvideVirtualStructure(ViewStructure structure) {
         mProvider.getViewDelegate().onProvideVirtualAssistStructure(structure);
     }
 
@@ -2576,4 +2578,18 @@
         super.onFinishTemporaryDetach();
         mProvider.getViewDelegate().onFinishTemporaryDetach();
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+
+        checkThread();
+        encoder.addProperty("webview:contentHeight", mProvider.getContentHeight());
+        encoder.addProperty("webview:contentWidth", mProvider.getContentWidth());
+        encoder.addProperty("webview:scale", mProvider.getScale());
+        encoder.addProperty("webview:title", mProvider.getTitle());
+        encoder.addProperty("webview:url", mProvider.getUrl());
+        encoder.addProperty("webview:originalUrl", mProvider.getOriginalUrl());
+    }
 }
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index d5787de..e367192 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -32,7 +32,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewAssistStructure;
+import android.view.ViewStructure;
 import android.view.ViewGroup.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -299,7 +299,7 @@
     interface ViewDelegate {
         public boolean shouldDelayChildPressedState();
 
-        public void onProvideVirtualAssistStructure(ViewAssistStructure structure);
+        public void onProvideVirtualAssistStructure(ViewStructure structure);
 
         public AccessibilityNodeProvider getAccessibilityNodeProvider();
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index c57a53a..9903b7e 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -56,6 +57,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
@@ -6330,6 +6332,16 @@
         public LayoutParams(ViewGroup.LayoutParams source) {
             super(source);
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+
+            encoder.addProperty("list:viewType", viewType);
+            encoder.addProperty("list:recycledHeaderFooter", recycledHeaderFooter);
+            encoder.addProperty("list:forceAdd", forceAdd);
+        }
     }
 
     /**
@@ -6912,6 +6924,25 @@
         }
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+
+        encoder.addProperty("drawing:cacheColorHint", getCacheColorHint());
+        encoder.addProperty("list:fastScrollEnabled", isFastScrollEnabled());
+        encoder.addProperty("list:scrollingCacheEnabled", isScrollingCacheEnabled());
+        encoder.addProperty("list:smoothScrollbarEnabled", isSmoothScrollbarEnabled());
+        encoder.addProperty("list:stackFromBottom", isStackFromBottom());
+        encoder.addProperty("list:textFilterEnabled", isTextFilterEnabled());
+
+        View selectedView = getSelectedView();
+        if (selectedView != null) {
+            encoder.addPropertyKey("selectedView");
+            selectedView.encode(encoder);
+        }
+    }
+
     /**
      * Abstract positon scroller used to handle smooth scrolling.
      */
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index e0b0e1f..f08141c 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -61,6 +61,7 @@
         implements ActionProvider.SubUiVisibilityListener {
     private static final String TAG = "ActionMenuPresenter";
     private static final int ITEM_ANIMATION_DURATION = 150;
+    private static final boolean ACTIONBAR_ANIMATIONS_ENABLED = false;
 
     private OverflowMenuButton mOverflowButton;
     private boolean mReserveOverflow;
@@ -414,7 +415,7 @@
     @Override
     public void updateMenuView(boolean cleared) {
         final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent();
-        if (menuViewParent != null) {
+        if (menuViewParent != null && ACTIONBAR_ANIMATIONS_ENABLED) {
             setupItemAnimations();
         }
         super.updateMenuView(cleared);
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index d6f2276..278a8fb 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -15,6 +15,7 @@
  */
 package android.widget;
 
+import android.annotation.NonNull;
 import android.annotation.StyleRes;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -28,6 +29,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import com.android.internal.view.menu.ActionMenuItemView;
 import com.android.internal.view.menu.MenuBuilder;
@@ -835,5 +837,17 @@
             super(width, height);
             this.isOverflowButton = isOverflowButton;
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+
+            encoder.addProperty("layout:overFlowButton", isOverflowButton);
+            encoder.addProperty("layout:cellsUsed", cellsUsed);
+            encoder.addProperty("layout:extraPixels", extraPixels);
+            encoder.addProperty("layout:expandable", expandable);
+            encoder.addProperty("layout:preventEdgeOffset", preventEdgeOffset);
+        }
     }
 }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 72cb0b5..54e3996 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.database.DataSetObserver;
@@ -29,6 +30,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -1245,4 +1247,16 @@
             }
         }
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+
+        encoder.addProperty("scrolling:firstPosition", mFirstPosition);
+        encoder.addProperty("list:nextSelectedPosition", mNextSelectedPosition);
+        encoder.addProperty("list:nextSelectedRowId", mNextSelectedRowId);
+        encoder.addProperty("list:selectedPosition", mSelectedPosition);
+        encoder.addProperty("list:itemCount", mItemCount);
+    }
 }
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 22e079c..6b4b2c7 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
+import android.view.ViewHierarchyEncoder;
 import com.android.internal.R;
 
 import android.annotation.DrawableRes;
@@ -459,4 +461,11 @@
         info.setCheckable(true);
         info.setChecked(mChecked);
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        super.encodeProperties(stream);
+        stream.addProperty("text:checked", isChecked());
+    }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index f2afeeb..770077d 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -17,8 +17,10 @@
 package android.widget;
 
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.PorterDuff;
+import android.view.ViewHierarchyEncoder;
 import com.android.internal.R;
 
 import android.content.Context;
@@ -530,9 +532,16 @@
     @Override
     public void onRestoreInstanceState(Parcelable state) {
         SavedState ss = (SavedState) state;
-  
+
         super.onRestoreInstanceState(ss.getSuperState());
         setChecked(ss.checked);
         requestLayout();
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        super.encodeProperties(stream);
+        stream.addProperty("checked", isChecked());
+    }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 712fdba..86a100f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -688,44 +688,101 @@
     private int getWordStart(int offset) {
         // FIXME - For this and similar methods we're not doing anything to check if there's
         // a LocaleSpan in the text, this may be something we should try handling or checking for.
-        int retOffset = getWordIteratorWithText().getBeginning(offset);
-        if (retOffset == BreakIterator.DONE) retOffset = offset;
-        return retOffset;
-    }
-
-    private int getWordEnd(int offset, boolean includePunctuation) {
-        int retOffset = getWordIteratorWithText().getEnd(offset);
-        if (retOffset == BreakIterator.DONE) {
-            retOffset = offset;
-        } else if (includePunctuation) {
-            retOffset = handlePunctuation(retOffset);
-        }
-        return retOffset;
-    }
-
-    private boolean isEndBoundary(int offset) {
-        int thisEnd = getWordEnd(offset, false);
-        return offset == thisEnd;
-    }
-
-    private boolean isStartBoundary(int offset) {
-        int thisStart = getWordStart(offset);
-        return thisStart == offset;
-    }
-
-    private int handlePunctuation(int offset) {
-        // FIXME - Check with UX how repeated ending punctuation should be handled.
-        // FIXME - Check with UX if / how we would handle non sentence ending characters.
-        // FIXME - Consider punctuation in different languages.
-        CharSequence text = mTextView.getText();
-        if (offset < text.length()) {
-            int c = Character.codePointAt(text, offset);
-            if (c == 0x002e /* period */|| c == 0x003f /* question mark */
-                    || c == 0x0021 /* exclamation mark */) {
-                offset = Character.offsetByCodePoints(text, offset, 1);
+        int retOffset = getWordIteratorWithText().prevBoundary(offset);
+        if (isPunctBoundaryBehind(retOffset, true /* isStart */)) {
+            // If we're on a punctuation boundary we should continue to get the
+            // previous offset until we're not longer on a punctuation boundary.
+            retOffset = getWordIteratorWithText().prevBoundary(retOffset);
+            while (!isPunctBoundaryBehind(retOffset, false /* isStart */)
+                    && retOffset != BreakIterator.DONE) {
+                retOffset = getWordIteratorWithText().prevBoundary(retOffset);
             }
         }
-        return offset;
+        if (retOffset == BreakIterator.DONE) {
+            return offset;
+        }
+        return retOffset;
+    }
+
+    private int getWordEnd(int offset) {
+        int retOffset = getWordIteratorWithText().nextBoundary(offset);
+        if (isPunctBoundaryForward(retOffset, true /* isStart */)) {
+            // If we're on a punctuation boundary we should continue to get the
+            // next offset until we're no longer on a punctuation boundary.
+            retOffset = getWordIteratorWithText().nextBoundary(retOffset);
+            while (!isPunctBoundaryForward(retOffset, false /* isStart */)
+                    && retOffset != BreakIterator.DONE) {
+                retOffset = getWordIteratorWithText().nextBoundary(retOffset);
+            }
+        }
+        if (retOffset == BreakIterator.DONE) {
+            return offset;
+        }
+        return retOffset;
+    }
+
+    /**
+     * Checks for punctuation boundaries for the provided offset and the
+     * previous character.
+     *
+     * @param offset The offset to check from.
+     * @param isStart Whether the boundary being checked for is at the start or
+     *            end of a punctuation sequence.
+     * @return Whether this is a punctuation boundary.
+     */
+    private boolean isPunctBoundaryBehind(int offset, boolean isStart) {
+        CharSequence text = mTextView.getText();
+        if (offset == BreakIterator.DONE || offset > text.length() || offset == 0) {
+            return false;
+        }
+        int cp = Character.codePointAt(text, offset);
+        int prevCp = Character.codePointBefore(text, offset);
+
+        if (isPunctuation(cp)) {
+            // If it's the start, the current cp and the prev cp are
+            // punctuation. If it's at the end of a punctuation sequence the
+            // current is punctuation and the prev is not.
+            return isStart ? isPunctuation(prevCp) : !isPunctuation(prevCp);
+        }
+        return false;
+    }
+
+    /**
+     * Checks for punctuation boundaries for the provided offset and the next
+     * character.
+     *
+     * @param offset The offset to check from.
+     * @param isStart Whether the boundary being checked for is at the start or
+     *            end of a punctuation sequence.
+     * @return Whether this is a punctuation boundary.
+     */
+    private boolean isPunctBoundaryForward(int offset, boolean isStart) {
+        CharSequence text = mTextView.getText();
+        if (offset == BreakIterator.DONE || offset > text.length() || offset == 0) {
+            return false;
+        }
+        int cp = Character.codePointBefore(text, offset);
+        int nextCpOffset = Math.min(offset + Character.charCount(cp), text.length() - 1);
+        int nextCp = Character.codePointBefore(text, nextCpOffset);
+
+        if (isPunctuation(cp)) {
+            // If it's the start, the current cp and the next cp are
+            // punctuation. If it's at the end of a punctuation sequence the
+            // current is punctuation and the next is not.
+            return isStart ? isPunctuation(nextCp) : !isPunctuation(nextCp);
+        }
+        return false;
+    }
+
+    private boolean isPunctuation(int cp) {
+        int type = Character.getType(cp);
+        return (type == Character.CONNECTOR_PUNCTUATION ||
+                type == Character.DASH_PUNCTUATION ||
+                type == Character.END_PUNCTUATION ||
+                type == Character.FINAL_QUOTE_PUNCTUATION ||
+                type == Character.INITIAL_QUOTE_PUNCTUATION ||
+                type == Character.OTHER_PUNCTUATION ||
+                type == Character.START_PUNCTUATION);
     }
 
     /**
@@ -788,7 +845,7 @@
             if (selectionStart == BreakIterator.DONE || selectionEnd == BreakIterator.DONE ||
                     selectionStart == selectionEnd) {
                 // Possible when the word iterator does not properly handle the text's language
-                long range = getCharRange(minOffset);
+                long range = getCharClusterRange(minOffset);
                 selectionStart = TextUtils.unpackRangeStartFromLong(range);
                 selectionEnd = TextUtils.unpackRangeEndFromLong(range);
             }
@@ -831,29 +888,25 @@
         return mWordIteratorWithText;
     }
 
-    private long getCharRange(int offset) {
+    private int getNextCursorOffset(int offset, boolean findAfterGivenOffset) {
+        final Layout layout = mTextView.getLayout();
+        if (layout == null) return offset;
+        final CharSequence text = mTextView.getText();
+        final int nextOffset = layout.getPaint().getTextRunCursor(text, 0, text.length(),
+                layout.isRtlCharAt(offset) ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR,
+                offset, findAfterGivenOffset ? Paint.CURSOR_AFTER : Paint.CURSOR_BEFORE);
+        return nextOffset == -1 ? offset : nextOffset;
+    }
+
+    private long getCharClusterRange(int offset) {
         final int textLength = mTextView.getText().length();
-        if (offset + 1 < textLength) {
-            final char currentChar = mTextView.getText().charAt(offset);
-            final char nextChar = mTextView.getText().charAt(offset + 1);
-            if (Character.isSurrogatePair(currentChar, nextChar)) {
-                return TextUtils.packRangeInLong(offset,  offset + 2);
-            }
-        }
         if (offset < textLength) {
-            return TextUtils.packRangeInLong(offset,  offset + 1);
-        }
-        if (offset - 2 >= 0) {
-            final char previousChar = mTextView.getText().charAt(offset - 1);
-            final char previousPreviousChar = mTextView.getText().charAt(offset - 2);
-            if (Character.isSurrogatePair(previousPreviousChar, previousChar)) {
-                return TextUtils.packRangeInLong(offset - 2,  offset);
-            }
+            return TextUtils.packRangeInLong(offset, getNextCursorOffset(offset, true));
         }
         if (offset - 1 >= 0) {
-            return TextUtils.packRangeInLong(offset - 1,  offset);
+            return TextUtils.packRangeInLong(getNextCursorOffset(offset, false), offset);
         }
-        return TextUtils.packRangeInLong(offset,  offset);
+        return TextUtils.packRangeInLong(offset, offset);
     }
 
     private boolean touchPositionIsInSelection() {
@@ -3903,13 +3956,9 @@
         public void updatePosition(float x, float y) {
             final int trueOffset = mTextView.getOffsetForPosition(x, y);
             final int currLine = mTextView.getLineAtCoordinate(y);
-
-            // Don't select white space on different lines.
-            if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return;
-
             boolean positionCursor = false;
             int offset = trueOffset;
-            int end = getWordEnd(offset, true);
+            int end = getWordEnd(offset);
             int start = getWordStart(offset);
 
             if (offset < mPreviousOffset) {
@@ -3925,7 +3974,7 @@
                     }
                 }
                 mTouchWordOffset = Math.max(trueOffset - offset, 0);
-                mInWord = !isStartBoundary(offset);
+                mInWord = !getWordIteratorWithText().isBoundary(offset);
                 positionCursor = true;
             } else if (offset - mTouchWordOffset > mPreviousOffset) {
                 // User is shrinking the selection.
@@ -3934,7 +3983,7 @@
                     offset = end;
                 }
                 offset -= mTouchWordOffset;
-                mInWord = !isEndBoundary(offset);
+                mInWord = !getWordIteratorWithText().isBoundary(offset);
                 positionCursor = true;
             }
 
@@ -3946,7 +3995,7 @@
                     int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
                     if (alteredOffset >= selectionEnd) {
                         // Can't pass the other drag handle.
-                        offset = Math.max(0, selectionEnd - 1);
+                        offset = getNextCursorOffset(selectionEnd, false);
                     } else {
                         offset = alteredOffset;
                     }
@@ -4005,14 +4054,9 @@
         public void updatePosition(float x, float y) {
             final int trueOffset = mTextView.getOffsetForPosition(x, y);
             final int currLine = mTextView.getLineAtCoordinate(y);
-
-            // Don't select white space on different lines.
-            if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return;
-
             int offset = trueOffset;
             boolean positionCursor = false;
-
-            int end = getWordEnd(offset, true);
+            int end = getWordEnd(offset);
             int start = getWordStart(offset);
 
             if (offset > mPreviousOffset) {
@@ -4028,7 +4072,7 @@
                     }
                 }
                 mTouchWordOffset = Math.max(offset - trueOffset, 0);
-                mInWord = !isEndBoundary(offset);
+                mInWord = !getWordIteratorWithText().isBoundary(offset);
                 positionCursor = true;
             } else if (offset + mTouchWordOffset < mPreviousOffset) {
                 // User is shrinking the selection.
@@ -4038,7 +4082,7 @@
                 }
                 offset += mTouchWordOffset;
                 positionCursor = true;
-                mInWord = !isStartBoundary(offset);
+                mInWord = !getWordIteratorWithText().isBoundary(offset);
             }
 
             if (positionCursor) {
@@ -4049,7 +4093,7 @@
                     int length = mTextView.getText().length();
                     if (alteredOffset <= selectionStart) {
                         // Can't pass the other drag handle.
-                        offset = Math.min(selectionStart + 1, length);
+                        offset = getNextCursorOffset(selectionStart, true);
                     } else {
                         offset = Math.min(alteredOffset, length);
                     }
@@ -4070,36 +4114,6 @@
     }
 
     /**
-     * Checks whether selection is happening on a different line than previous and
-     * if that line only contains whitespace up to the touch location.
-     *
-     * @param prevLine The previous line the selection was on.
-     * @param currLine The current line being selected.
-     * @param offset The offset in the text where the touch occurred.
-     * @return Whether or not it was just a white space line being selected.
-     */
-    private boolean isWhitespaceLine(int prevLine, int currLine, int offset) {
-        if (prevLine == currLine) {
-            // Same line; don't care.
-            return false;
-        }
-        CharSequence text = mTextView.getText();
-        if (offset == text.length()) {
-            // No character at the last position.
-            return false;
-        }
-        int lineEndOffset = mTextView.getLayout().getLineEnd(currLine);
-        for (int cp, i = offset; i < lineEndOffset; i += Character.charCount(cp)) {
-            cp = Character.codePointAt(text, i);
-            if (!Character.isSpaceChar(cp) && !Character.isWhitespace(cp)) {
-                // There are non white space chars on the line.
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
      * A CursorController instance can be used to control a cursor in the text.
      */
     private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener {
@@ -4178,8 +4192,6 @@
         private int mStartOffset = -1;
         // Indicates whether the user is selecting text and using the drag accelerator.
         private boolean mDragAcceleratorActive;
-        // Indicates the line of text the drag accelerator is on.
-        private int mPrevLine = -1;
 
         SelectionModifierCursorController() {
             resetTouchOffsets();
@@ -4272,8 +4284,6 @@
                         }
                     }
 
-                    // New selection, reset line.
-                    mPrevLine = mTextView.getLineAtCoordinate(y);
                     mDownPositionX = x;
                     mDownPositionY = y;
                     mGestureStayedInTapRegion = true;
@@ -4318,7 +4328,7 @@
                         // We don't start "dragging" until the user is past the initial word that
                         // gets selected on long press.
                         int firstWordStart = getWordStart(mStartOffset);
-                        int firstWordEnd = getWordEnd(mStartOffset, false);
+                        int firstWordEnd = getWordEnd(mStartOffset);
                         if (offset > firstWordEnd || offset < firstWordStart) {
 
                             // Basically the goal in the below code is to have the highlight be
@@ -4330,13 +4340,6 @@
                             if (my > fingerOffset) my -= fingerOffset;
                             offset = mTextView.getOffsetForPosition(mx, my);
 
-                            int currLine = mTextView.getLineAtCoordinate(my);
-
-                            // Don't select white space on different lines.
-                            if (isWhitespaceLine(mPrevLine, currLine, offset)) return;
-
-                            mPrevLine = currLine;
-
                             // Perform the check for closeness at edge of view, if we're very close
                             // don't adjust the offset to be in front of the finger - otherwise the
                             // user can't select words at the edge.
@@ -4365,7 +4368,7 @@
 
                             // Need to adjust start offset based on direction of movement.
                             int newStart = mStartOffset < offset ? getWordStart(mStartOffset)
-                                    : getWordEnd(mStartOffset, true);
+                                    : getWordEnd(mStartOffset);
                             Selection.setSelection((Spannable) mTextView.getText(), newStart,
                                     offset);
                         }
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 0602944..7ca450a 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -33,6 +33,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.widget.RemoteViews.RemoteView;
 
 import com.android.internal.R;
@@ -407,6 +408,18 @@
         return FrameLayout.class.getName();
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+
+        encoder.addProperty("measurement:measureAllChildren", mMeasureAllChildren);
+        encoder.addProperty("padding:foregroundPaddingLeft", mForegroundPaddingLeft);
+        encoder.addProperty("padding:foregroundPaddingTop", mForegroundPaddingTop);
+        encoder.addProperty("padding:foregroundPaddingRight", mForegroundPaddingRight);
+        encoder.addProperty("padding:foregroundPaddingBottom", mForegroundPaddingBottom);
+    }
+
     /**
      * Per-child layout information for layouts that support margins.
      * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index c959774..dcaafa5 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -31,6 +32,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -2420,4 +2422,11 @@
                 row, 1, column, 1, isHeading, isSelected);
         info.setCollectionItemInfo(itemInfo);
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+        encoder.addProperty("numColumns", getNumColumns());
+    }
 }
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 0879c5d..cf67905 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -35,6 +36,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -1695,6 +1697,13 @@
         return ss;
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+        encoder.addProperty("layout:fillViewPort", mFillViewport);
+    }
+
     static class SavedState extends BaseSavedState {
         public int scrollPosition;
         public boolean isLayoutRtl;
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 6d2f368..05059bc 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -43,6 +44,7 @@
 import android.view.RemotableViewMethod;
 import android.view.View;
 import android.view.ViewDebug;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
@@ -1431,4 +1433,11 @@
     public CharSequence getAccessibilityClassName() {
         return ImageView.class.getName();
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        super.encodeProperties(stream);
+        stream.addProperty("layout:baseline", getBaseline());
+    }
 }
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 72f51c9..f153ce5 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -19,6 +19,7 @@
 import com.android.internal.R;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -29,6 +30,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.widget.RemoteViews.RemoteView;
 
 import java.lang.annotation.Retention;
@@ -1813,6 +1815,20 @@
         return LinearLayout.class.getName();
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+        encoder.addProperty("layout:baselineAligned", mBaselineAligned);
+        encoder.addProperty("layout:baselineAlignedChildIndex", mBaselineAlignedChildIndex);
+        encoder.addProperty("measurement:baselineChildTop", mBaselineChildTop);
+        encoder.addProperty("measurement:orientation", mOrientation);
+        encoder.addProperty("measurement:gravity", mGravity);
+        encoder.addProperty("measurement:totalLength", mTotalLength);
+        encoder.addProperty("layout:totalLength", mTotalLength);
+        encoder.addProperty("layout:useLargestChild", mUseLargestChild);
+    }
+
     /**
      * Per-child layout information associated with ViewLinearLayout.
      * 
@@ -1921,5 +1937,14 @@
             return output + "LinearLayout.LayoutParams={width=" + sizeToString(width) +
                     ", height=" + sizeToString(height) + " weight=" + weight +  "}";
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+
+            encoder.addProperty("layout:weight", weight);
+            encoder.addProperty("layout:gravity", gravity);
+        }
     }
 }
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 05866f0..94b9416 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1791,8 +1791,9 @@
 
     private class ResizePopupRunnable implements Runnable {
         public void run() {
-            if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() &&
-                    mDropDownList.getChildCount() <= mListItemExpandMaximum) {
+            if (mDropDownList != null && mDropDownList.isAttachedToWindow()
+                    && mDropDownList.getCount() > mDropDownList.getChildCount()
+                    && mDropDownList.getChildCount() <= mListItemExpandMaximum) {
                 mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
                 show();
             }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index a79c8e8..7dcaa1f 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -23,6 +23,7 @@
 import com.google.android.collect.Lists;
 
 import android.annotation.IdRes;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -40,6 +41,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.ViewParent;
 import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -3938,4 +3940,12 @@
                 position, 1, 0, 1, isHeading, isSelected);
         info.setCollectionItemInfo(itemInfo);
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+
+        encoder.addProperty("recycleOnMeasure", recycleOnMeasure());
+    }
 }
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index b59ae17..639a09c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.PorterDuff;
 
@@ -49,6 +50,7 @@
 import android.view.RemotableViewMethod;
 import android.view.View;
 import android.view.ViewDebug;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AlphaAnimation;
@@ -1893,6 +1895,17 @@
         postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        super.encodeProperties(stream);
+
+        stream.addProperty("progress:max", getMax());
+        stream.addProperty("progress:progress", getProgress());
+        stream.addProperty("progress:secondaryProgress", getSecondaryProgress());
+        stream.addProperty("progress:indeterminate", isIndeterminate());
+    }
+
     /**
      * Command for sending an accessibility event.
      */
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index d12739f..affc5da 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.util.ArrayMap;
 import com.android.internal.R;
 
@@ -36,6 +37,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
@@ -1616,6 +1618,13 @@
             // This will set the layout direction
             super.resolveLayoutDirection(layoutDirection);
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+            encoder.addProperty("layout:alignWithParent", alignWithParent);
+        }
     }
 
     private static class DependencyGraph {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 98d61d3..2709f25 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -38,6 +39,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -1787,6 +1789,13 @@
         return ss;
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+        super.encodeProperties(encoder);
+        encoder.addProperty("fillViewport", mFillViewport);
+    }
+
     static class SavedState extends BaseSavedState {
         public int scrollPosition;
 
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index f94f97c..ff587c2 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -26,13 +26,11 @@
 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;
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
-import android.os.Bundle;
 import android.text.Layout;
 import android.text.StaticLayout;
 import android.text.TextPaint;
@@ -46,7 +44,7 @@
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
 import android.view.VelocityTracker;
-import android.view.ViewAssistStructure;
+import android.view.ViewStructure;
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -1363,8 +1361,8 @@
     }
 
     @Override
-    public void onProvideAssistStructure(ViewAssistStructure structure) {
-        super.onProvideAssistStructure(structure);
+    public void onProvideStructure(ViewStructure structure) {
+        super.onProvideStructure(structure);
         CharSequence switchText = isChecked() ? mTextOn : mTextOff;
         if (!TextUtils.isEmpty(switchText)) {
             CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index f73ee49..d4288d6 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -24,7 +25,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
-
+import android.view.ViewHierarchyEncoder;
 
 /**
  * <p>A layout that arranges its children horizontally. A TableRow should
@@ -509,6 +510,14 @@
                 height = WRAP_CONTENT;
             }
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+            encoder.addProperty("layout:column", column);
+            encoder.addProperty("layout:span", span);
+        }
     }
 
     // special transparent hierarchy change listener
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index e2acaac..5d7b569 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -32,6 +33,7 @@
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
 import android.view.RemotableViewMethod;
+import android.view.ViewHierarchyEncoder;
 
 import com.android.internal.R;
 
@@ -546,4 +548,18 @@
         mTime.setTimeInMillis(System.currentTimeMillis());
         setText(DateFormat.format(mFormat, mTime));
     }
+
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        super.encodeProperties(stream);
+
+        CharSequence s = getFormat12Hour();
+        stream.addProperty("format12Hour", s == null ? null : s.toString());
+
+        s = getFormat24Hour();
+        stream.addProperty("format24Hour", s == null ? null : s.toString());
+        stream.addProperty("format", mFormat == null ? null : mFormat.toString());
+        stream.addProperty("hasSeconds", mHasSeconds);
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 449173f..68c49cd 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -114,12 +114,13 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewAssistStructure;
+import android.view.ViewStructure;
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewRootImpl;
 import android.view.ViewTreeObserver;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -2844,7 +2845,8 @@
             @ViewDebug.IntToString(from = Typeface.BOLD_ITALIC, to = "BOLD_ITALIC")
     })
     public int getTypefaceStyle() {
-        return mTextPaint.getTypeface().getStyle();
+        Typeface typeface = mTextPaint.getTypeface();
+        return typeface != null ? typeface.getStyle() : Typeface.NORMAL;
     }
 
     /**
@@ -8713,8 +8715,8 @@
     }
 
     @Override
-    public void onProvideAssistStructure(ViewAssistStructure structure) {
-        super.onProvideAssistStructure(structure);
+    public void onProvideStructure(ViewStructure structure) {
+        super.onProvideStructure(structure);
         final boolean isPassword = hasPasswordTransformationMethod();
         if (!isPassword) {
             structure.setText(getText(), getSelectionStart(), getSelectionEnd());
@@ -9556,6 +9558,23 @@
         }
     }
 
+    /** @hide */
+    @Override
+    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
+        super.encodeProperties(stream);
+
+        TruncateAt ellipsize = getEllipsize();
+        stream.addProperty("text:ellipsize", ellipsize == null ? null : ellipsize.name());
+        stream.addProperty("text:textSize", getTextSize());
+        stream.addProperty("text:scaledTextSize", getScaledTextSize());
+        stream.addProperty("text:typefaceStyle", getTypefaceStyle());
+        stream.addProperty("text:selectionStart", getSelectionStart());
+        stream.addProperty("text:selectionEnd", getSelectionEnd());
+        stream.addProperty("text:curTextColor", mCurTextColor);
+        stream.addProperty("text:text", mText == null ? null : mText.toString());
+        stream.addProperty("text:gravity", mGravity);
+    }
+
     /**
      * User interface state that is stored by TextView for implementing
      * {@link View#onSaveInstanceState}.
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 6173832..9277f9b 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.Build;
+import android.view.View;
 
 /**
  * Log all the things.
@@ -33,6 +34,10 @@
     public static final int ACTION_BAN_APP_NOTES = 146;
     public static final int NOTIFICATION_ZEN_MODE_EVENT_RULE = 147;
     public static final int ACTION_DISMISS_ALL_NOTES = 148;
+    public static final int QS_DND_DETAILS = 149;
+    public static final int QS_BLUETOOTH_DETAILS = 150;
+    public static final int QS_CAST_DETAILS = 151;
+    public static final int QS_WIFI_DETAILS = 152;
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
@@ -41,13 +46,27 @@
         EventLogTags.writeSysuiViewVisibility(category, 100);
     }
 
-    public static void hidden(Context context, int category) {
+    public static void hidden(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
             throw new IllegalArgumentException("Must define metric category");
         }
         EventLogTags.writeSysuiViewVisibility(category, 0);
     }
 
+    public static void visibility(Context context, int category, boolean visibile)
+            throws IllegalArgumentException {
+        if (visibile) {
+            visible(context, category);
+        } else {
+            hidden(context, category);
+        }
+    }
+
+    public static void visibility(Context context, int category, int vis)
+            throws IllegalArgumentException {
+        visibility(context, category, vis == View.VISIBLE);
+    }
+
     public static void action(Context context, int category) {
         action(context, category, "");
     }
diff --git a/core/java/com/android/internal/transition/EpicenterClipReveal.java b/core/java/com/android/internal/transition/EpicenterClipReveal.java
deleted file mode 100644
index 1a6736a..0000000
--- a/core/java/com/android/internal/transition/EpicenterClipReveal.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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.internal.transition;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.RectEvaluator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.transition.TransitionValues;
-import android.transition.Visibility;
-import android.util.AttributeSet;
-import android.util.Property;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
-import android.view.animation.PathInterpolator;
-
-import com.android.internal.R;
-
-/**
- * EpicenterClipReveal captures the {@link View#getClipBounds()} before and
- * after the scene change and animates between those and the epicenter bounds
- * during a visibility transition.
- */
-public class EpicenterClipReveal extends Visibility {
-    private static final String PROPNAME_CLIP = "android:epicenterReveal:clip";
-    private static final String PROPNAME_BOUNDS = "android:epicenterReveal:bounds";
-
-    private final TimeInterpolator mInterpolatorX;
-    private final TimeInterpolator mInterpolatorY;
-    private final boolean mCenterClipBounds;
-
-    public EpicenterClipReveal() {
-        mInterpolatorX = null;
-        mInterpolatorY = null;
-        mCenterClipBounds = false;
-    }
-
-    public EpicenterClipReveal(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        final TypedArray a = context.obtainStyledAttributes(attrs,
-                R.styleable.EpicenterClipReveal, 0, 0);
-
-        mCenterClipBounds = a.getBoolean(R.styleable.EpicenterClipReveal_centerClipBounds, false);
-
-        final int interpolatorX = a.getResourceId(R.styleable.EpicenterClipReveal_interpolatorX, 0);
-        if (interpolatorX != 0) {
-            mInterpolatorX = AnimationUtils.loadInterpolator(context, interpolatorX);
-        } else {
-            mInterpolatorX = TransitionConstants.LINEAR_OUT_SLOW_IN;
-        }
-
-        final int interpolatorY = a.getResourceId(R.styleable.EpicenterClipReveal_interpolatorY, 0);
-        if (interpolatorY != 0) {
-            mInterpolatorY = AnimationUtils.loadInterpolator(context, interpolatorY);
-        } else {
-            mInterpolatorY = TransitionConstants.FAST_OUT_SLOW_IN;
-        }
-
-        a.recycle();
-    }
-
-    @Override
-    public void captureStartValues(TransitionValues transitionValues) {
-        super.captureStartValues(transitionValues);
-        captureValues(transitionValues);
-    }
-
-    @Override
-    public void captureEndValues(TransitionValues transitionValues) {
-        super.captureEndValues(transitionValues);
-        captureValues(transitionValues);
-    }
-
-    private void captureValues(TransitionValues values) {
-        final View view = values.view;
-        if (view.getVisibility() == View.GONE) {
-            return;
-        }
-
-        final Rect clip = view.getClipBounds();
-        values.values.put(PROPNAME_CLIP, clip);
-
-        if (clip == null) {
-            final Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
-            values.values.put(PROPNAME_BOUNDS, bounds);
-        }
-    }
-
-    @Override
-    public Animator onAppear(ViewGroup sceneRoot, View view,
-            TransitionValues startValues, TransitionValues endValues) {
-        if (endValues == null) {
-            return null;
-        }
-
-        final Rect end = getBestRect(endValues);
-        final Rect start = getEpicenterOrCenter(end);
-
-        // Prepare the view.
-        view.setClipBounds(start);
-
-        return createRectAnimator(view, start, end, endValues, mInterpolatorX, mInterpolatorY);
-    }
-
-    @Override
-    public Animator onDisappear(ViewGroup sceneRoot, View view,
-            TransitionValues startValues, TransitionValues endValues) {
-        if (startValues == null) {
-            return null;
-        }
-
-        final Rect start = getBestRect(startValues);
-        final Rect end = getEpicenterOrCenter(start);
-
-        // Prepare the view.
-        view.setClipBounds(start);
-
-        return createRectAnimator(view, start, end, endValues, mInterpolatorX, mInterpolatorY);
-    }
-
-    private Rect getEpicenterOrCenter(Rect bestRect) {
-        final Rect epicenter = getEpicenter();
-        if (epicenter != null) {
-            // Translate the clip bounds to be centered within the target bounds.
-            if (mCenterClipBounds) {
-                final int offsetX = bestRect.centerX() - epicenter.centerX();
-                final int offsetY = bestRect.centerY() - epicenter.centerY();
-                epicenter.offset(offsetX, offsetY);
-            }
-            return epicenter;
-        }
-
-        final int centerX = bestRect.centerX();
-        final int centerY = bestRect.centerY();
-        return new Rect(centerX, centerY, centerX, centerY);
-    }
-
-    private Rect getBestRect(TransitionValues values) {
-        final Rect clipRect = (Rect) values.values.get(PROPNAME_CLIP);
-        if (clipRect == null) {
-            return (Rect) values.values.get(PROPNAME_BOUNDS);
-        }
-        return clipRect;
-    }
-
-    private static Animator createRectAnimator(final View view, Rect start, Rect end,
-            TransitionValues endValues, TimeInterpolator interpolatorX,
-            TimeInterpolator interpolatorY) {
-        final RectEvaluator evaluator = new RectEvaluator(new Rect());
-        final Rect terminalClip = (Rect) endValues.values.get(PROPNAME_CLIP);
-
-        final ClipDimenProperty propX = new ClipDimenProperty(ClipDimenProperty.TARGET_X);
-        final ObjectAnimator animX = ObjectAnimator.ofObject(view, propX, evaluator, start, end);
-        if (interpolatorX != null) {
-            animX.setInterpolator(interpolatorX);
-        }
-
-        final ClipDimenProperty propY = new ClipDimenProperty(ClipDimenProperty.TARGET_Y);
-        final ObjectAnimator animY = ObjectAnimator.ofObject(view, propY, evaluator, start, end);
-        if (interpolatorY != null) {
-            animY.setInterpolator(interpolatorY);
-        }
-
-        final AnimatorSet animSet = new AnimatorSet();
-        animSet.playTogether(animX, animY);
-        animSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                view.setClipBounds(terminalClip);
-            }
-        });
-        return animSet;
-    }
-
-    private static class ClipDimenProperty extends Property<View, Rect> {
-        public static final char TARGET_X = 'x';
-        public static final char TARGET_Y = 'y';
-
-        private final Rect mTempRect = new Rect();
-
-        private final int mTargetDimension;
-
-        public ClipDimenProperty(char targetDimension) {
-            super(Rect.class, "clip_bounds_" + targetDimension);
-
-            mTargetDimension = targetDimension;
-        }
-
-        @Override
-        public Rect get(View object) {
-            final Rect tempRect = mTempRect;
-            if (!object.getClipBounds(tempRect)) {
-                tempRect.setEmpty();
-            }
-            return tempRect;
-        }
-
-        @Override
-        public void set(View object, Rect value) {
-            final Rect tempRect = mTempRect;
-            if (object.getClipBounds(tempRect)) {
-                if (mTargetDimension == TARGET_X) {
-                    tempRect.left = value.left;
-                    tempRect.right = value.right;
-                } else {
-                    tempRect.top = value.top;
-                    tempRect.bottom = value.bottom;
-                }
-                object.setClipBounds(tempRect);
-            }
-        }
-    }
-}
diff --git a/core/java/com/android/internal/transition/EpicenterTranslate.java b/core/java/com/android/internal/transition/EpicenterTranslate.java
deleted file mode 100644
index eac3ff8..0000000
--- a/core/java/com/android/internal/transition/EpicenterTranslate.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.internal.transition;
-
-import com.android.internal.R;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.transition.TransitionValues;
-import android.transition.Visibility;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
-
-/**
- * EpicenterTranslate captures the {@link View#getTranslationX()} and
- * {@link View#getTranslationY()} before and after the scene change and
- * animates between those and the epicenter's center during a visibility
- * transition.
- */
-public class EpicenterTranslate extends Visibility {
-    private static final String PROPNAME_BOUNDS = "android:epicenterReveal:bounds";
-    private static final String PROPNAME_TRANSLATE_X = "android:epicenterReveal:translateX";
-    private static final String PROPNAME_TRANSLATE_Y = "android:epicenterReveal:translateY";
-    private static final String PROPNAME_TRANSLATE_Z = "android:epicenterReveal:translateZ";
-    private static final String PROPNAME_Z = "android:epicenterReveal:z";
-
-    private final TimeInterpolator mInterpolatorX;
-    private final TimeInterpolator mInterpolatorY;
-    private final TimeInterpolator mInterpolatorZ;
-
-    public EpicenterTranslate() {
-        mInterpolatorX = null;
-        mInterpolatorY = null;
-        mInterpolatorZ = null;
-    }
-
-    public EpicenterTranslate(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        final TypedArray a = context.obtainStyledAttributes(attrs,
-                R.styleable.EpicenterTranslate, 0, 0);
-
-        final int interpolatorX = a.getResourceId(R.styleable.EpicenterTranslate_interpolatorX, 0);
-        if (interpolatorX != 0) {
-            mInterpolatorX = AnimationUtils.loadInterpolator(context, interpolatorX);
-        } else {
-            mInterpolatorX = TransitionConstants.FAST_OUT_SLOW_IN;
-        }
-
-        final int interpolatorY = a.getResourceId(R.styleable.EpicenterTranslate_interpolatorY, 0);
-        if (interpolatorY != 0) {
-            mInterpolatorY = AnimationUtils.loadInterpolator(context, interpolatorY);
-        } else {
-            mInterpolatorY = TransitionConstants.FAST_OUT_SLOW_IN;
-        }
-
-        final int interpolatorZ = a.getResourceId(R.styleable.EpicenterTranslate_interpolatorZ, 0);
-        if (interpolatorZ != 0) {
-            mInterpolatorZ = AnimationUtils.loadInterpolator(context, interpolatorZ);
-        } else {
-            mInterpolatorZ = TransitionConstants.FAST_OUT_SLOW_IN;
-        }
-
-        a.recycle();
-    }
-
-    @Override
-    public void captureStartValues(TransitionValues transitionValues) {
-        super.captureStartValues(transitionValues);
-        captureValues(transitionValues);
-    }
-
-    @Override
-    public void captureEndValues(TransitionValues transitionValues) {
-        super.captureEndValues(transitionValues);
-        captureValues(transitionValues);
-    }
-
-    private void captureValues(TransitionValues values) {
-        final View view = values.view;
-        if (view.getVisibility() == View.GONE) {
-            return;
-        }
-
-        final Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
-        values.values.put(PROPNAME_BOUNDS, bounds);
-        values.values.put(PROPNAME_TRANSLATE_X, view.getTranslationX());
-        values.values.put(PROPNAME_TRANSLATE_Y, view.getTranslationY());
-        values.values.put(PROPNAME_TRANSLATE_Z, view.getTranslationZ());
-        values.values.put(PROPNAME_Z, view.getZ());
-    }
-
-    @Override
-    public Animator onAppear(ViewGroup sceneRoot, View view,
-            TransitionValues startValues, TransitionValues endValues) {
-        if (endValues == null) {
-            return null;
-        }
-
-        final Rect end = (Rect) endValues.values.get(PROPNAME_BOUNDS);
-        final Rect start = getEpicenterOrCenter(end);
-        final float startX = start.centerX() - end.centerX();
-        final float startY = start.centerY() - end.centerY();
-        final float startZ = 0 - (float) endValues.values.get(PROPNAME_Z);
-
-        // Translate the view to be centered on the epicenter.
-        view.setTranslationX(startX);
-        view.setTranslationY(startY);
-        view.setTranslationZ(startZ);
-
-        final float endX = (float) endValues.values.get(PROPNAME_TRANSLATE_X);
-        final float endY = (float) endValues.values.get(PROPNAME_TRANSLATE_Y);
-        final float endZ = (float) endValues.values.get(PROPNAME_TRANSLATE_Z);
-        return createAnimator(view, startX, startY, startZ, endX, endY, endZ,
-                mInterpolatorX, mInterpolatorY, mInterpolatorZ);
-    }
-
-    @Override
-    public Animator onDisappear(ViewGroup sceneRoot, View view,
-            TransitionValues startValues, TransitionValues endValues) {
-        if (startValues == null) {
-            return null;
-        }
-
-        final Rect start = (Rect) endValues.values.get(PROPNAME_BOUNDS);
-        final Rect end = getEpicenterOrCenter(start);
-        final float endX = end.centerX() - start.centerX();
-        final float endY = end.centerY() - start.centerY();
-        final float endZ = 0 - (float) startValues.values.get(PROPNAME_Z);
-
-        final float startX = (float) endValues.values.get(PROPNAME_TRANSLATE_X);
-        final float startY = (float) endValues.values.get(PROPNAME_TRANSLATE_Y);
-        final float startZ = (float) endValues.values.get(PROPNAME_TRANSLATE_Z);
-        return createAnimator(view, startX, startY, startZ, endX, endY, endZ,
-                mInterpolatorX, mInterpolatorY, mInterpolatorZ);
-    }
-
-    private Rect getEpicenterOrCenter(Rect bestRect) {
-        final Rect epicenter = getEpicenter();
-        if (epicenter != null) {
-            return epicenter;
-        }
-
-        final int centerX = bestRect.centerX();
-        final int centerY = bestRect.centerY();
-        return new Rect(centerX, centerY, centerX, centerY);
-    }
-
-    private static Animator createAnimator(final View view, float startX, float startY,
-            float startZ, float endX, float endY, float endZ, TimeInterpolator interpolatorX,
-            TimeInterpolator interpolatorY, TimeInterpolator interpolatorZ) {
-        final ObjectAnimator animX = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, startX, endX);
-        if (interpolatorX != null) {
-            animX.setInterpolator(interpolatorX);
-        }
-
-        final ObjectAnimator animY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY);
-        if (interpolatorY != null) {
-            animY.setInterpolator(interpolatorY);
-        }
-
-        final ObjectAnimator animZ = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, startZ, endZ);
-        if (interpolatorZ != null) {
-            animZ.setInterpolator(interpolatorZ);
-        }
-
-        final AnimatorSet animSet = new AnimatorSet();
-        animSet.playTogether(animX, animY, animZ);
-        return animSet;
-    }
-}
diff --git a/core/java/com/android/internal/transition/EpicenterTranslateClipReveal.java b/core/java/com/android/internal/transition/EpicenterTranslateClipReveal.java
new file mode 100644
index 0000000..2c10297
--- /dev/null
+++ b/core/java/com/android/internal/transition/EpicenterTranslateClipReveal.java
@@ -0,0 +1,328 @@
+/*
+ * 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.internal.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.TypeEvaluator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.transition.TransitionValues;
+import android.transition.Visibility;
+import android.util.AttributeSet;
+import android.util.Property;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
+
+import com.android.internal.R;
+
+/**
+ * EpicenterTranslateClipReveal captures the clip bounds and translation values
+ * before and after the scene change and animates between those and the
+ * epicenter bounds during a visibility transition.
+ */
+public class EpicenterTranslateClipReveal extends Visibility {
+    private static final String PROPNAME_CLIP = "android:epicenterReveal:clip";
+    private static final String PROPNAME_BOUNDS = "android:epicenterReveal:bounds";
+    private static final String PROPNAME_TRANSLATE_X = "android:epicenterReveal:translateX";
+    private static final String PROPNAME_TRANSLATE_Y = "android:epicenterReveal:translateY";
+    private static final String PROPNAME_TRANSLATE_Z = "android:epicenterReveal:translateZ";
+    private static final String PROPNAME_Z = "android:epicenterReveal:z";
+
+    private final TimeInterpolator mInterpolatorX;
+    private final TimeInterpolator mInterpolatorY;
+    private final TimeInterpolator mInterpolatorZ;
+
+    public EpicenterTranslateClipReveal() {
+        mInterpolatorX = null;
+        mInterpolatorY = null;
+        mInterpolatorZ = null;
+    }
+
+    public EpicenterTranslateClipReveal(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.EpicenterTranslateClipReveal, 0, 0);
+
+        final int interpolatorX = a.getResourceId(
+                R.styleable.EpicenterTranslateClipReveal_interpolatorX, 0);
+        if (interpolatorX != 0) {
+            mInterpolatorX = AnimationUtils.loadInterpolator(context, interpolatorX);
+        } else {
+            mInterpolatorX = TransitionConstants.LINEAR_OUT_SLOW_IN;
+        }
+
+        final int interpolatorY = a.getResourceId(
+                R.styleable.EpicenterTranslateClipReveal_interpolatorY, 0);
+        if (interpolatorY != 0) {
+            mInterpolatorY = AnimationUtils.loadInterpolator(context, interpolatorY);
+        } else {
+            mInterpolatorY = TransitionConstants.FAST_OUT_SLOW_IN;
+        }
+
+        final int interpolatorZ = a.getResourceId(
+                R.styleable.EpicenterTranslateClipReveal_interpolatorZ, 0);
+        if (interpolatorZ != 0) {
+            mInterpolatorZ = AnimationUtils.loadInterpolator(context, interpolatorZ);
+        } else {
+            mInterpolatorZ = TransitionConstants.FAST_OUT_SLOW_IN;
+        }
+
+        a.recycle();
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        super.captureStartValues(transitionValues);
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        super.captureEndValues(transitionValues);
+        captureValues(transitionValues);
+    }
+
+    private void captureValues(TransitionValues values) {
+        final View view = values.view;
+        if (view.getVisibility() == View.GONE) {
+            return;
+        }
+
+        final Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
+        values.values.put(PROPNAME_BOUNDS, bounds);
+        values.values.put(PROPNAME_TRANSLATE_X, view.getTranslationX());
+        values.values.put(PROPNAME_TRANSLATE_Y, view.getTranslationY());
+        values.values.put(PROPNAME_TRANSLATE_Z, view.getTranslationZ());
+        values.values.put(PROPNAME_Z, view.getZ());
+
+        final Rect clip = view.getClipBounds();
+        values.values.put(PROPNAME_CLIP, clip);
+    }
+
+    @Override
+    public Animator onAppear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (endValues == null) {
+            return null;
+        }
+
+        final Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
+        final Rect startBounds = getEpicenterOrCenter(endBounds);
+        final float startX = startBounds.centerX() - endBounds.centerX();
+        final float startY = startBounds.centerY() - endBounds.centerY();
+        final float startZ = 0 - (float) endValues.values.get(PROPNAME_Z);
+
+        // Translate the view to be centered on the epicenter.
+        view.setTranslationX(startX);
+        view.setTranslationY(startY);
+        view.setTranslationZ(startZ);
+
+        final float endX = (float) endValues.values.get(PROPNAME_TRANSLATE_X);
+        final float endY = (float) endValues.values.get(PROPNAME_TRANSLATE_Y);
+        final float endZ = (float) endValues.values.get(PROPNAME_TRANSLATE_Z);
+
+        final Rect endClip = getBestRect(endValues);
+        final Rect startClip = getEpicenterOrCenter(endClip);
+
+        // Prepare the view.
+        view.setClipBounds(startClip);
+
+        final State startStateX = new State(startClip.left, startClip.right, startX);
+        final State endStateX = new State(endClip.left, endClip.right, endX);
+        final State startStateY = new State(startClip.top, startClip.bottom, startY);
+        final State endStateY = new State(endClip.top, endClip.bottom, endY);
+
+        return createRectAnimator(view, startStateX, startStateY, startZ, endStateX, endStateY,
+                endZ, endValues, mInterpolatorX, mInterpolatorY, mInterpolatorZ);
+    }
+
+    @Override
+    public Animator onDisappear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (startValues == null) {
+            return null;
+        }
+
+        final Rect startBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
+        final Rect endBounds = getEpicenterOrCenter(startBounds);
+        final float endX = endBounds.centerX() - startBounds.centerX();
+        final float endY = endBounds.centerY() - startBounds.centerY();
+        final float endZ = 0 - (float) startValues.values.get(PROPNAME_Z);
+
+        final float startX = (float) endValues.values.get(PROPNAME_TRANSLATE_X);
+        final float startY = (float) endValues.values.get(PROPNAME_TRANSLATE_Y);
+        final float startZ = (float) endValues.values.get(PROPNAME_TRANSLATE_Z);
+
+        final Rect startClip = getBestRect(startValues);
+        final Rect endClip = getEpicenterOrCenter(startClip);
+
+        // Prepare the view.
+        view.setClipBounds(startClip);
+
+        final State startStateX = new State(startClip.left, startClip.right, startX);
+        final State endStateX = new State(endClip.left, endClip.right, endX);
+        final State startStateY = new State(startClip.top, startClip.bottom, startY);
+        final State endStateY = new State(endClip.top, endClip.bottom, endY);
+
+        return createRectAnimator(view, startStateX, startStateY, startZ, endStateX, endStateY,
+                endZ, endValues, mInterpolatorX, mInterpolatorY, mInterpolatorZ);
+    }
+
+    private Rect getEpicenterOrCenter(Rect bestRect) {
+        final Rect epicenter = getEpicenter();
+        if (epicenter != null) {
+            return epicenter;
+        }
+
+        final int centerX = bestRect.centerX();
+        final int centerY = bestRect.centerY();
+        return new Rect(centerX, centerY, centerX, centerY);
+    }
+
+    private Rect getBestRect(TransitionValues values) {
+        final Rect clipRect = (Rect) values.values.get(PROPNAME_CLIP);
+        if (clipRect == null) {
+            return (Rect) values.values.get(PROPNAME_BOUNDS);
+        }
+        return clipRect;
+    }
+
+    private static Animator createRectAnimator(final View view, State startX, State startY,
+            float startZ, State endX, State endY, float endZ, TransitionValues endValues,
+            TimeInterpolator interpolatorX, TimeInterpolator interpolatorY,
+            TimeInterpolator interpolatorZ) {
+        final StateEvaluator evaluator = new StateEvaluator();
+
+        final ObjectAnimator animZ = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, startZ, endZ);
+        if (interpolatorZ != null) {
+            animZ.setInterpolator(interpolatorZ);
+        }
+
+        final StateProperty propX = new StateProperty(StateProperty.TARGET_X);
+        final ObjectAnimator animX = ObjectAnimator.ofObject(view, propX, evaluator, startX, endX);
+        if (interpolatorX != null) {
+            animX.setInterpolator(interpolatorX);
+        }
+
+        final StateProperty propY = new StateProperty(StateProperty.TARGET_Y);
+        final ObjectAnimator animY = ObjectAnimator.ofObject(view, propY, evaluator, startY, endY);
+        if (interpolatorY != null) {
+            animY.setInterpolator(interpolatorY);
+        }
+
+        final Rect terminalClip = (Rect) endValues.values.get(PROPNAME_CLIP);
+        final AnimatorListenerAdapter animatorListener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                view.setClipBounds(terminalClip);
+            }
+        };
+
+        final AnimatorSet animSet = new AnimatorSet();
+        animSet.playTogether(animX, animY, animZ);
+        animSet.addListener(animatorListener);
+        return animSet;
+    }
+
+    private static class State {
+        int lower;
+        int upper;
+        float trans;
+
+        public State() {}
+
+        public State(int lower, int upper, float trans) {
+            this.lower = lower;
+            this.upper = upper;
+            this.trans = trans;
+        }
+    }
+
+    private static class StateEvaluator implements TypeEvaluator<State> {
+        private final State mTemp = new State();
+
+        @Override
+        public State evaluate(float fraction, State startValue, State endValue) {
+            mTemp.upper = startValue.upper + (int) ((endValue.upper - startValue.upper) * fraction);
+            mTemp.lower = startValue.lower + (int) ((endValue.lower - startValue.lower) * fraction);
+            mTemp.trans = startValue.trans + (int) ((endValue.trans - startValue.trans) * fraction);
+            return mTemp;
+        }
+    }
+
+    private static class StateProperty extends Property<View, State> {
+        public static final char TARGET_X = 'x';
+        public static final char TARGET_Y = 'y';
+
+        private final Rect mTempRect = new Rect();
+        private final State mTempState = new State();
+
+        private final int mTargetDimension;
+
+        public StateProperty(char targetDimension) {
+            super(State.class, "state_" + targetDimension);
+
+            mTargetDimension = targetDimension;
+        }
+
+        @Override
+        public State get(View object) {
+            final Rect tempRect = mTempRect;
+            if (!object.getClipBounds(tempRect)) {
+                tempRect.setEmpty();
+            }
+            final State tempState = mTempState;
+            if (mTargetDimension == TARGET_X) {
+                tempState.trans = object.getTranslationX();
+                tempState.lower = tempRect.left + (int) tempState.trans;
+                tempState.upper = tempRect.right + (int) tempState.trans;
+            } else {
+                tempState.trans = object.getTranslationY();
+                tempState.lower = tempRect.top + (int) tempState.trans;
+                tempState.upper = tempRect.bottom + (int) tempState.trans;
+            }
+            return tempState;
+        }
+
+        @Override
+        public void set(View object, State value) {
+            final Rect tempRect = mTempRect;
+            if (object.getClipBounds(tempRect)) {
+                if (mTargetDimension == TARGET_X) {
+                    tempRect.left = value.lower - (int) value.trans;
+                    tempRect.right = value.upper - (int) value.trans;
+                } else {
+                    tempRect.top = value.lower - (int) value.trans;
+                    tempRect.bottom = value.upper - (int) value.trans;
+                }
+                object.setClipBounds(tempRect);
+            }
+
+            if (mTargetDimension == TARGET_X) {
+                object.setTranslationX(value.trans);
+            } else {
+                object.setTranslationY(value.trans);
+            }
+        }
+    }
+}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 9babe82..2785c48 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -224,7 +224,7 @@
 }
 
 void Bitmap::reconfigure(const SkImageInfo& info) {
-    reconfigure(info, mPixelRef->rowBytes(), mPixelRef->colorTable());
+    reconfigure(info, info.minRowBytes(), nullptr);
 }
 
 void Bitmap::detachFromJava() {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index db495dd..74a9e4e 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -976,6 +976,12 @@
     dest->setTo(*src);
 }
 
+static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
+{
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+    theme->clear();
+}
+
 static jint android_content_AssetManager_loadThemeAttributeValue(
     JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
 {
@@ -2108,6 +2114,8 @@
         (void*) android_content_AssetManager_applyThemeStyle },
     { "copyTheme", "(JJ)V",
         (void*) android_content_AssetManager_copyTheme },
+    { "clearTheme", "(J)V",
+        (void*) android_content_AssetManager_clearTheme },
     { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadThemeAttributeValue },
     { "getThemeChangingConfigurations", "(J)I",
diff --git a/core/res/res/drawable-hdpi/text_cursor_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 0179433..0000000
--- a/core/res/res/drawable-hdpi/text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index e5760be..0000000
--- a/core/res/res/drawable-mdpi/text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_cursor_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 3939214..0000000
--- a/core/res/res/drawable-xhdpi/text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_cursor_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 432c385..0000000
--- a/core/res/res/drawable-xxhdpi/text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/text_cursor_material.xml b/core/res/res/drawable/text_cursor_material.xml
index a350c47..0bedaa9 100644
--- a/core/res/res/drawable/text_cursor_material.xml
+++ b/core/res/res/drawable/text_cursor_material.xml
@@ -14,6 +14,15 @@
      limitations under the License.
 -->
 
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/text_cursor_mtrl_alpha"
-    android:tint="?attr/colorControlActivated" />
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:inset="2dp">
+    <shape
+        android:tint="?attr/colorControlActivated"
+        android:shape="rectangle">
+        <size
+            android:height="2dp"
+            android:width="2dp" />
+        <solid
+            android:color="@color/white" />
+    </shape>
+</inset>
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 89c3749..4b544d2 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -16,7 +16,6 @@
 -->
 
 <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-            xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
 
@@ -27,8 +26,7 @@
         android:layout_column="0"
         android:layout_row="0"
         android:layout_rowSpan="3"
-        android:layout_gravity="center|fill"
-        tools:background="@color/accent_material_light" />
+        android:layout_gravity="center|fill" />
 
     <RelativeLayout
         android:layout_width="wrap_content"
@@ -56,20 +54,14 @@
                 android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
                 android:singleLine="true"
                 android:ellipsize="none"
-                android:gravity="right"
-                tools:text="23"
-                tools:textSize="@dimen/timepicker_time_label_size"
-                tools:textColor="@color/white" />
+                android:gravity="right" />
 
             <TextView
                 android:id="@+id/separator"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
-                android:importantForAccessibility="no"
-                tools:text=":"
-                tools:textSize="@dimen/timepicker_time_label_size"
-                tools:textColor="@color/white" />
+                android:importantForAccessibility="no" />
 
             <!-- The minutes should always be to the right of the separator,
                  regardless of the current locale's layout direction. -->
@@ -80,10 +72,7 @@
                 android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
                 android:singleLine="true"
                 android:ellipsize="none"
-                android:gravity="left"
-                tools:text="59"
-                tools:textSize="@dimen/timepicker_time_label_size"
-                tools:textColor="@color/white" />
+                android:gravity="left" />
         </LinearLayout>
 
         <!-- The layout alignment of this view will switch between toRightOf
@@ -106,10 +95,7 @@
                 android:paddingTop="@dimen/timepicker_am_top_padding"
                 android:lines="1"
                 android:ellipsize="none"
-                android:includeFontPadding="false"
-                tools:text="AM"
-                tools:textSize="@dimen/timepicker_ampm_label_size"
-                tools:textColor="@color/white" />
+                android:includeFontPadding="false" />
 
             <CheckedTextView
                 android:id="@+id/pm_label"
@@ -121,10 +107,7 @@
                 android:paddingTop="@dimen/timepicker_pm_top_padding"
                 android:lines="1"
                 android:ellipsize="none"
-                android:includeFontPadding="false"
-                tools:text="PM"
-                tools:textSize="@dimen/timepicker_ampm_label_size"
-                tools:textColor="@color/white" />
+                android:includeFontPadding="false" />
         </LinearLayout>
     </RelativeLayout>
 
diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml
index 2150341..a4388f6 100644
--- a/core/res/res/layout/date_picker_header_material.xml
+++ b/core/res/res/layout/date_picker_header_material.xml
@@ -16,17 +16,13 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:tools="http://schemas.android.com/tools"
               android:id="@+id/date_picker_header"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:paddingBottom="18dp"
               android:paddingStart="?attr/dialogPreferredPadding"
               android:paddingEnd="?attr/dialogPreferredPadding"
-              android:orientation="vertical"
-              tools:background="@color/accent_material_light"
-              tools:paddingStart="24dp"
-              tools:paddingEnd="24dp">
+              android:orientation="vertical">
 
     <!-- Top padding should stay on this view so that
          the touch target is a bit larger. -->
@@ -35,10 +31,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingTop="16dp"
-        android:textAppearance="@style/TextAppearance.Material.DatePicker.YearLabel"
-        tools:text="2015"
-        tools:textSize="@dimen/date_picker_year_label_size"
-        tools:textColor="@color/white" />
+        android:textAppearance="@style/TextAppearance.Material.DatePicker.YearLabel" />
 
     <TextView
         android:id="@+id/date_picker_header_date"
@@ -47,9 +40,6 @@
         android:textAppearance="@style/TextAppearance.Material.DatePicker.DateLabel"
         android:gravity="start"
         android:maxLines="2"
-        android:ellipsize="none"
-        tools:text="Thu, Sep 30"
-        tools:textSize="@dimen/date_picker_date_label_size"
-        tools:textColor="@color/white" />
+        android:ellipsize="none" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/time_picker_header_material.xml b/core/res/res/layout/time_picker_header_material.xml
index be9e443..3f5e300 100644
--- a/core/res/res/layout/time_picker_header_material.xml
+++ b/core/res/res/layout/time_picker_header_material.xml
@@ -18,13 +18,11 @@
 <!-- This layout is duplicated in land/time_picker_material.xml, so any
      changes made here need to be manually copied over. -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                xmlns:tools="http://schemas.android.com/tools"
                 android:id="@+id/time_header"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:orientation="horizontal"
-                android:padding="@dimen/timepicker_separator_padding"
-                tools:background="@color/accent_material_light">
+                android:padding="@dimen/timepicker_separator_padding">
 
     <!-- The hour should always be to the left of the separator,
          regardless of the current locale's layout direction. -->
@@ -37,10 +35,7 @@
         android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
         android:singleLine="true"
         android:ellipsize="none"
-        android:gravity="right"
-        tools:text="23"
-        tools:textSize="@dimen/timepicker_time_label_size"
-        tools:textColor="@color/white" />
+        android:gravity="right" />
 
     <TextView
         android:id="@+id/separator"
@@ -50,10 +45,7 @@
         android:layout_marginRight="@dimen/timepicker_separator_padding"
         android:layout_centerInParent="true"
         android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
-        android:importantForAccessibility="no"
-        tools:text=":"
-        tools:textSize="@dimen/timepicker_time_label_size"
-        tools:textColor="@color/white" />
+        android:importantForAccessibility="no" />
 
     <!-- The minutes should always be to the left of the separator,
          regardless of the current locale's layout direction. -->
@@ -66,10 +58,7 @@
         android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
         android:singleLine="true"
         android:ellipsize="none"
-        android:gravity="left"
-        tools:text="59"
-        tools:textSize="@dimen/timepicker_time_label_size"
-        tools:textColor="@color/white" />
+        android:gravity="left" />
 
     <!-- The layout alignment of this view will switch between toRightOf
          @id/minutes and toLeftOf @id/hours depending on the locale. -->
@@ -90,10 +79,7 @@
             android:paddingTop="@dimen/timepicker_am_top_padding"
             android:textAppearance="@style/TextAppearance.Material.TimePicker.AmPmLabel"
             android:lines="1"
-            android:ellipsize="none"
-            tools:text="AM"
-            tools:textSize="@dimen/timepicker_ampm_label_size"
-            tools:textColor="@color/white" />
+            android:ellipsize="none" />
         <CheckedTextView
             android:id="@+id/pm_label"
             android:layout_width="wrap_content"
@@ -103,9 +89,6 @@
             android:paddingTop="@dimen/timepicker_pm_top_padding"
             android:textAppearance="@style/TextAppearance.Material.TimePicker.AmPmLabel"
             android:lines="1"
-            android:ellipsize="none"
-            tools:text="PM"
-            tools:textSize="@dimen/timepicker_ampm_label_size"
-            tools:textColor="@color/white" />
+            android:ellipsize="none" />
     </LinearLayout>
 </RelativeLayout>
diff --git a/core/res/res/transition/popup_window_enter.xml b/core/res/res/transition/popup_window_enter.xml
index 38c41f0..c4c8dac 100644
--- a/core/res/res/transition/popup_window_enter.xml
+++ b/core/res/res/transition/popup_window_enter.xml
@@ -16,17 +16,14 @@
 
 <transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
                android:transitionOrdering="together">
-    <!-- Start from location of epicenter, move to popup location. -->
-    <transition
-        class="com.android.internal.transition.EpicenterTranslate"
-        android:duration="300" />
-
     <!-- Start from size of epicenter, expand to full width/height. -->
     <transition
-        class="com.android.internal.transition.EpicenterClipReveal"
-        android:centerClipBounds="true"
-        android:duration="300" />
+        class="com.android.internal.transition.EpicenterTranslateClipReveal"
+        android:duration="250" />
 
     <!-- Quickly fade in. -->
-    <fade android:duration="100" />
+    <fade
+        android:duration="100"
+        android:fromAlpha="0.1"
+        android:toAlpha="1.0" />
 </transitionSet>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1c4b5f7..0b96d22 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2347,11 +2347,6 @@
              be saved. -->
         <attr name="saveEnabled" format="boolean" />
 
-        <!-- If true, no {@link android.view.ViewAssistStructure} data will be collected from
-             this view or any of its children.  The default is false, allowing assist structure
-             to be reported by it. -->
-        <attr name="assistBlocked" format="boolean" />
-
         <!-- Specifies whether to filter touches when the view's window is obscured by
              another visible window.  When set to true, the view will not receive touches
              whenever a toast, dialog or other window appears above the view's window.
@@ -5877,16 +5872,9 @@
     </declare-styleable>
 
     <!-- @hide For internal use only. Use only as directed. -->
-    <declare-styleable name="EpicenterClipReveal">
-        <attr name="centerClipBounds" format="boolean" />
+    <declare-styleable name="EpicenterTranslateClipReveal">
         <attr name="interpolatorX" format="reference" />
         <attr name="interpolatorY" format="reference" />
-    </declare-styleable>
-
-    <!-- @hide For internal use only. Use only as directed. -->
-    <declare-styleable name="EpicenterTranslate">
-        <attr name="interpolatorX" />
-        <attr name="interpolatorY" />
         <attr name="interpolatorZ" format="reference" />
     </declare-styleable>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 297b302..e403a16 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2682,7 +2682,9 @@
   <!-- NFC CardEmulation: dynamically load service resources -->
   <public type="attr" name="dynamicResources" />
 
-  <public type="attr" name="assistBlocked" />
+  <attr name="__reserved0" format="boolean" />
+  <public type="attr" name="__reserved0" />
+
   <public type="attr" name="stylusButtonPressable" />
   <public type="attr" name="supportsLaunchVoiceAssistFromKeyguard" />
   <public type="attr" name="scrollIndicators" />
diff --git a/docs/html/design/building-blocks/buttons.jd b/docs/html/design/building-blocks/buttons.jd
deleted file mode 100644
index 713574a..0000000
--- a/docs/html/design/building-blocks/buttons.jd
+++ /dev/null
@@ -1,99 +0,0 @@
-page.title=Buttons
-page.tags=button,input
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/buttons.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Buttons<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/button.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Buttons</p>
-  </div>
-</a>
-
-<p itemprop="description">A button consists of text and/or an image that clearly communicates what action
-  will occur when the user touches it. A button can have an image, text, or both.
-</p>
-
-<div class="cols" style="margin-top:22px">
-  <div class="col-3">
-    <img src="{@docRoot}design/media/icon_magnifying_glass.png" style="height:64px;padding:20px 0 0 40px;">
-  </div>
-  <div class="col-3">
-    <img src="{@docRoot}design/media/buttons_text.png"  style="height:94px;">
-  </div>
-  <div class="col-7">
-    <img src="{@docRoot}design/media/buttons_image_and_text.png"  style="height:94px;">
-  </div>
-</div>
-
-<div class="cols" style="margin-top:0;">
-  <div class="col-3">
-      <p>An image alone works best when the action can be represented by a symbol that's well understood.</p>
-  </div>
-  <div class="col-3">
-      <p>Text alone is most appropriate for actions that would be difficult to
-      represent visually, or are critical to convey in words to avoid any ambiguity.</p>
-  </div>
-  <div class="col-7">
-    <p>
-      Both an icon and text is most appropriate when they complement each other:
-      each carrying its own bit of information, but together making a larger whole.
-    </p>
-
-    <p>
-      For example, in a birthday reminder card in Google Now, the button's text
-      describes the action while its image indicates that the action will be done
-      in Google+.
-    </p>
-  </div>
-</div>
-
-<h3>What about button backgrounds?</h3>
-
-<div class="cols">
-  <div class="col-6">
-    <p>For <strong>image-only</strong> buttons, a background isn't necessary because
-    users are accustomed to interacting with objects.</p>
-
-    <div class="cols" style="margin-left:72px">
-      <div class="col-2">
-        <div class="do-dont-label bad emulate-content-left-padding" style="width:30px">Don't</div>
-        <img src="{@docRoot}design/media/buttons_image_bg_dont.png" style="padding-left:14px;">
-      </div>
-      <div class="col-2" style="width:29px;margin-left:10px;">
-        <div class="do-dont-label good"><strong>Do</strong></div>
-        <img src="{@docRoot}design/media/icon_alarm.png" style="width:31px;padding-top:7px;">
-      </div>
-    </div>
-  </div>
-
-<div class="col-7">
-<p>
-  For buttons <strong>with text</strong>, a background is also usually
-  unnecessary. To invite users to touch, phrase it as a clear action (e.g.
-  "Start", "Sign in") and use different color and formatting than the screen's
-  usual body text.
-</p>
-
-<p>
-  Use buttons with backgrounds sparingly. Because they have a heavy appearance,
-  they work best when there's only one or two of them on the screen. They're
-  most appropriate for:
-</p>
-
-<ul>
-  <li>A call to action you really want users to pursue (e.g. "Sign up")</li>
-  <li>A key decision point (e.g. "Accept" / "Decline")</li>
-  <li>When the user is about to commit a significant action (e.g. "Erase
-  everything", "Buy now")</li>
-</ul>
-</div>
-</div>
-
diff --git a/docs/html/design/building-blocks/dialogs.jd b/docs/html/design/building-blocks/dialogs.jd
deleted file mode 100644
index 70460ba..0000000
--- a/docs/html/design/building-blocks/dialogs.jd
+++ /dev/null
@@ -1,186 +0,0 @@
-page.title=Dialogs
-page.tags=dialog,alert,popup,toast
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/dialogs.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Dialogs<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/dialogs.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Dialogs</p>
-  </div>
-</a>
-
-<p itemprop="description">Dialogs prompt the user for decisions or additional information required by the app to continue a
-task. Such requests can range from simple Cancel/OK decisions to more complex layouts asking the
-user to adjust settings or enter text.</p>
-
-<img src="{@docRoot}design/media/dialogs_main.png">
-
-<div class="with-callouts">
-
-<ol>
-  <li>
-  <h4>Optional title region</h4>
-  <p>The title introduces the content of your dialog. It can, for example, identify the name of a
-   setting that the user is about to change, or request a decision.</p>
-  </li>
-  <li>
-  <h4>Content area</h4>
-  <p>Dialog content varies widely. For settings dialogs, a dialog may contain UI elements such as
-   sliders, text fields, checkboxes, or radio buttons that allow the user to change app or system
-   settings. In other cases, such as alerts, the content may consist solely of text that provides
-   further context for a user decision.</p>
-  </li>
-
-  <li>
-  <h4>Action buttons</h4>
-  <p>Action buttons are typically Cancel and/or OK, with OK indicating the preferred or most likely action. However, if the options consist of specific actions such as Close or Wait rather than a confirmation or cancellation of the action described in the content, then all the buttons should be active verbs. Order actions following these rules:</p>
-    <ul>
-
-    <li>The dismissive action of a dialog is always on the left. Dismissive actions return to the user to the previous state.</li>
-    <li>The affirmative actions are on the right. Affirmative actions continue progress toward the user goal that triggered the dialog.</li>
-    </ul>
-  </li>
-</ol>
-</div>
-
-<img src="{@docRoot}design/media/dialogs_examples.png">
-<div class="figure-caption">
-  Samples of typical dialog use in Android.
-</div>
-
-<h2 id="alerts">Alerts</h2>
-
-<p>Alerts inform the user about a situation that requires their confirmation or acknowledgement before
-proceeding. They differ slightly in appearance based upon the severity and impact of the message
-conveyed.</p>
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/dialogs_w_no_title.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Alerts without title bars</h4>
-<p>Most alerts don't need titles. Usually the decision doesn't have a severe impact and can be summed
-up succinctly in a sentence or two. The content area should either ask a question (such as "Delete
-this conversation?") or make a clear statement whose relationship to the action buttons is obvious.</p>
-
-  </div>
-</div>
-
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/dialogs_w_title.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Alerts with title bars</h4>
-<p>Use alerts with title bars sparingly. They are appropriate only when a high-risk operation involving
-potential loss of data, connectivity, extra charges, and so on requires a clear question or
-statement (the title) and some additional explanation (in the content area).</p>
-<p>Keep the question or statement short: for example, "Erase USB storage?" Avoid apologies. A user
-should be able to skip the content completely and still have a clear idea of what choices are
-available based on the title and the text of the action buttons.</p>
-
-  </div>
-</div>
-<p>When crafting a confirmation dialog, make the title meaningful by echoing the requested action.</p>
-
-<div class="cols">
-  <div class="col-4">
-    <div class="do-dont-label bad">Don't</div>
-      <table class="ui-table bad">
-      <thead>
-        <tr>
-          <th class="label">
-          Are you sure?
-          </th>
-        </tr>
-      </thead>
-      </table>
-  </div>
-  <div class="col-4">
-    <div class="do-dont-label bad">Don't</div>
-      <table class="ui-table bad">
-      <thead>
-        <tr>
-          <th class="label">
-          Warning!
-          </th>
-        </tr>
-      </thead>
-      </table>
-  </div>
-  <div class="col-5">
-    <div class="do-dont-label good">Do</div>
-      <table class="ui-table good">
-      <thead>
-        <tr>
-          <th class="label">
-          Erase USB storage?
-          </th>
-        </tr>
-      </thead>
-      </table>
-  </div>
-</div>
-
-
-<h2 id="popups">Popups</h2>
-
-<p>Popups are lightweight version of dialogs that require a single selection from the user. Popups
-don't have have explicit buttons that accept or cancel the operation. Instead, making a selection
-advances the workflow, and simply touching outside the popup dismisses it.</p>
-
-<img src="{@docRoot}design/media/dialogs_popups_example.png">
-
-
-<h2 id="toasts">Toasts</h2>
-
-
-<div class="cols">
-  <div class="col-6">
-
-    <div class="vspace size-3"></div>
-
-<p>Toasts provide lightweight feedback about an operation in a small popup. For example, navigating
-away from an email before you send it triggers a "Draft saved" toast to let you know that you can
-continue editing later. Toasts automatically disappear after a timeout.</p>
-
-<a class="notice-designers-material left"
-  href="http://www.google.com/design/spec/components/snackbars-toasts.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Toasts<p>
-  </div>
-</a>
-
-
-<a class="notice-developers left" href="{@docRoot}guide/topics/ui/notifiers/toasts.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Toasts</p>
-  </div>
-</a>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/dialogs_toasts.png">
-
-  </div>
-</div>
-
diff --git a/docs/html/design/building-blocks/grid-lists.jd b/docs/html/design/building-blocks/grid-lists.jd
deleted file mode 100644
index 7a1c652..0000000
--- a/docs/html/design/building-blocks/grid-lists.jd
+++ /dev/null
@@ -1,96 +0,0 @@
-page.title=Grid Lists
-page.tags=gridview,layout,listview
-@jd:body
-
-<img src="{@docRoot}design/media/gridview_overview.png">
-
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/grid-lists.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Grid lists<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/layout/gridview.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Grid View</p>
-  </div>
-</a>
-
-<p itemprop="description">Grid lists are an alternative to standard list views. They are best suited for showing data sets
-that represent themselves through images. In contrast to simple lists, grid lists may scroll either
-vertically or horizontally.</p>
-
-
-
-<h2 id="generic_grid">Generic Grids</h2>
-
-
-<p>The items in a grid list are arranged in two dimensions, one of which is fixed when scrolling
-content. The scrolling direction dictates the ordering of the items within the grid list. Since the
-scrolling direction is not deterministic, make it easy for the user to determine the orientation by
-cutting off grid items to communicate where the overflow is located.</p>
-<p>Avoid creating grid lists that scroll in two dimensions.</p>
-
-
-<div class="cols">
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/gridview_vertical.png">
-
-  </div>
-  <div class="col-6">
-
-<h4>Vertical scrolling</h4>
-<p>Vertically scrolling grid list items are sorted in traditional western reading direction:
-left-to-right and top-down. When displaying the list, cut off the items in the bottom row to
-communicate that the user can scroll the list down to show additional items. Be sure to retain this
-scheme when the user rotates the screen.</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/gridview_horizontal.png">
-
-  </div>
-  <div class="col-6">
-
-<h4>Horizontal scrolling</h4>
-<p>Horizontally scrolling lists fix the vertical axis of the item grid. Compared to vertically
-scrolling lists, the sorting changes slightly to a top-down and left-to-right arrangement. Employ
-the same technique of cutting off the items in the rightmost column to indicate the scrolling
-direction.</p>
-<p>Don't use scrolling tabs as a means to switch views in conjunction with horizontally scrolling grid
-lists, because the horizontal gesture for view and content navigation will conflict. If you show
-scrolling tabs for view navigation together with a grid list, use vertical grid scrolling for list
-navigation.</p>
-
-  </div>
-</div>
-
-
-<h2 id="with-labels">Grid List with Labels</h2>
-
-<p>Use labels to display additional contextual information for your grid list items.</p>
-
-
-<div class="cols">
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/gridview_style.png">
-
-  </div>
-  <div class="col-6">
-
-<h4>Style</h4>
-<p>Use semi-transparent panels on top of the grid list items to display your labels. This allows you to
-control the contrast and ensures legibility of the labels while letting the content "shine through".</p>
-
-  </div>
-</div>
diff --git a/docs/html/design/building-blocks/index.jd b/docs/html/design/building-blocks/index.jd
deleted file mode 100644
index 7fb0e55..0000000
--- a/docs/html/design/building-blocks/index.jd
+++ /dev/null
@@ -1,30 +0,0 @@
-page.title=Building Blocks
-header.justLinks=1
-footer.hide=1
-@jd:body
-
-<style>
-#landing-graphic-container {
-  position: relative;
-}
-
-#text-overlay {
-  position: absolute;
-  left: 0;
-  top: 520px;
-  width: 450px;
-}
-</style>
-
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    <span itemprop="description">Your inventory of ready-to-use elements for creating
-    outstanding apps.</span>
-    <br><br>
-    <a href="{@docRoot}design/building-blocks/tabs.html" class="landing-page-link">Tabs</a>
-  </div>
-
-  <a href="{@docRoot}design/building-blocks/tabs.html">
-    <img src="{@docRoot}design/media/building_blocks_landing.png">
-  </a>
-</div>
diff --git a/docs/html/design/building-blocks/lists.jd b/docs/html/design/building-blocks/lists.jd
deleted file mode 100644
index 85753c8..0000000
--- a/docs/html/design/building-blocks/lists.jd
+++ /dev/null
@@ -1,56 +0,0 @@
-page.title=Lists
-page.tags=listview,layout
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/lists.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Lists<p>
-  </div>
-</a>
-
-<p itemprop="description">Lists present multiple line items in a vertical arrangement. They can be used for data selection as
-well as drilldown navigation.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="cols clearfix">
-  <div class="col-9">
-
-    <img src="{@docRoot}design/media/lists_main.png">
-
-  </div>
-  <div class="col-4 with-callouts">
-
-<ol style="margin-bottom: 60px;">
-<li>
-<h4>Section Divider</h4>
-<p>Use section dividers to organize the content of your list into groups and facilitate scanning.</p>
-</li>
-<li>
-<h4>Line Items</h4>
-<p>List items can accommodate a wide range of data types in different arrangements, including
- simple single-line items, multi-line items, and custom items with icons, checkboxes, and action
- buttons.</p>
-</li>
-</ol>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/layout/listview.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>List View</p>
-  </div>
-</a>
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/lists-controls.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Lists: Controls<p>
-  </div>
-</a>
-
-
-  </div>
-</div>
diff --git a/docs/html/design/building-blocks/pickers.jd b/docs/html/design/building-blocks/pickers.jd
deleted file mode 100644
index 72da0f7..0000000
--- a/docs/html/design/building-blocks/pickers.jd
+++ /dev/null
@@ -1,40 +0,0 @@
-page.title=Pickers
-page.tags=datepicker,timepicker
-@jd:body
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/pickers.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Pickers</p>
-  </div>
-</a>
-
-<p itemprop="description">Pickers provide a simple way to select a single value from a set. In addition to touching the
-up/down arrow buttons, it's possible to set the desired value from the keyboard or via a swipe
-gesture.</p>
-
-<div class="cols">
-  <div class="col-6">
-
-    <img src="{@docRoot}design/media/picker_space.png">
-
-  </div>
-  <div class="col-6">
-
-<h4>Space considerations</h4>
-<p>Pickers can be used inline on a form, but their relatively large footprint is best suited for
-display in a dialog. For inline display, consider using more compact controls such as text fields or
-spinners.</p>
-
-  </div>
-</div>
-
-<h2 id="date-time">Date and time pickers</h2>
-
-<p>Android provides these as ready-to-use dialogs. Each picker is a dialog with a set of controls for
-entering the parts of the date (month, day, year) or time (hour, minute, AM/PM). Using these in your
-app helps ensure that a user's specification of a data or time input is valid and formatted
-correctly. The format of a time and date picker adjusts automatically to the locale.</p>
-
-<img src="{@docRoot}design/media/picker_datetime.png">
-
diff --git a/docs/html/design/building-blocks/progress.jd b/docs/html/design/building-blocks/progress.jd
deleted file mode 100644
index ae81440..0000000
--- a/docs/html/design/building-blocks/progress.jd
+++ /dev/null
@@ -1,105 +0,0 @@
-page.title=Progress &amp; Activity
-page.tags=progressbar,download,network
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/progress-activity.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Progress and Activity<p>
-  </div>
-</a>
-
-<p>Progress bars and activity indicators signal to users that something is happening that will take a moment.</p>
-<h2 id="progress">Progress bars</h2>
-
-<p>Progress bars are for situations where the percentage completed can be determined. They give users a quick sense of how much longer an operation will take.</p>
-
-<img src="{@docRoot}design/media/progress_download.png">
-
-<p>A progress bar should always fill from 0% to 100% and never move backwards to a lower value. If multiple operations are happening in sequence, use the progress bar to represent the delay as a whole, so that when the bar reaches 100%, it doesn't return back to 0%.</p>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<img src="{@docRoot}design/media/progress_themes.png">
-<div class="figure-caption">
-  Progress bar in Holo Dark and Holo Light.
-</div>
-
-<h2 id="activity">Activity indicators</h2>
-
-<p>Activity indicators are for operations of an indeterminate length. They ask users to wait a moment while something finishes up, without getting into specifics about what's happening behind the scenes.</p>
-
-<p>Two styles are available: a bar and a circle. Each is offered in a variety of sizes, in both Holo Light and Holo Dark themes. Choose the appropriate style and size for the surrounding context. For example, the largest activity circle works well when displayed in a blank content area, but not in a smaller dialog box. Each operation should only be represented by one activity indicator.</p>
-
-<div class="cols">
-  <div class="col-6">
-
-    <img src="{@docRoot}design/media/progress_activity.png">
-
-  </div>
-  <div class="col-7 with-callouts">
-
-    <ol>
-      <li class="value-1"><h4>Activity bar</h4>
-        <p>In this example, an activity bar (in Holo Dark) appears when a user first requests a download. There's an unknown period of time when the download has not yet started. As soon as the download starts, this activity bar transforms into a progress bar.</p>
-      </li>
-    </ol>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-6">
-
-    <img src="{@docRoot}design/media/progress_activity2.png">
-
-  </div>
-  <div class="col-7 with-callouts">
-
-    <ol>
-      <li class="value-2"><h4>Activity circle</h4>
-        <p>In this example, an activity circle (in Holo Light) is used in the Gmail application when a message is being loaded because it's not possible to determine how long it will take to download the email.</p>
-        <p>When displaying an activity circle, do not include text to communicate what the app is doing. The moving circle alone provides sufficient feedback about the delay, and does so in an understated way that minimizes the impact.</p>
-        <p>
-        <div style="margin-left:0;margin-top:1em;">
-          <img src="{@docRoot}design/media/progress_activity_do_dont.png">
-        </div>
-        </p>
-      </li>
-    </ol>
-
-  </div>
-</div>
-
-<h2 id="custom-indicators">Custom indicators</h2>
-<p>The standard progress bar and activity indicators work well for most situations and should be used whenever possible to provide a consistent experience across Android. However, some situations may call for something more custom.</p>
-
-<p>Here's an example:<br>
-In all of the Google Play apps (Music, Books, Movies, Magazines), we wanted the current download state of each item to be visible at all times at the top-level screen. These states are:
-  <ul>
-    <li>Not downloaded</li>
-    <li>Temporarily downloaded (automatically cached by the app)</li>
-    <li>Permanently downloaded on the device at the user's request</li>
-  </ul>
-</p>
-<p>We also needed to indicate progress from one download state to another, because downloading is not instantaneous.</p>
-<p>This presented a challenge, because the Google Play apps use a variety of different layouts, and some of them are highly space-constrained. We didn't want this information to clutter the top-level screens, or compete too much with the cover art.</p>
-<p>So we designed a custom indicator that could show all of the information in a tiny footprint, with the flexibility to appear on top of content if necessary.</p>
-
-<img src="{@docRoot}design/media/progress_activity_custom.png">
-
-<p>The color indicates whether it's downloaded (blue) or not (gray). The appearance of the pin indicates whether the download is permanent (white, upright) or temporary (gray, diagonal). And when state is in the process of changing, progress is indicated by a moving pie chart.</p>
-
-<div class="cols">
-  <div class="col-9">
-    <img src="{@docRoot}design/media/progress_activity_custom_app.png">
-  </div>
-  <div class="col-4">
-    <div class="figure-caption">
-      Across Google Play apps with different layouts, the same custom indicator appears with each item. It communicates download state as well as progress, in a compact package that can be incorporated into any screen design.
-    </div>
-  </div>
-</div>
-
-<p>If you find that the standard indicators aren't meeting your needs (due to space constraints, state complexities), by all means design your own. Make it feel like part of the Android family by injecting some of the visual characteristics of the standard indicators. In this example, we carried over the circular shape, the same shade of blue, and the flat and simple style.</p>
diff --git a/docs/html/design/building-blocks/scrolling.jd b/docs/html/design/building-blocks/scrolling.jd
deleted file mode 100644
index 04b1e4a..0000000
--- a/docs/html/design/building-blocks/scrolling.jd
+++ /dev/null
@@ -1,39 +0,0 @@
-page.title=Scrolling
-page.tags=scrollview,listview
-@jd:body
-
-
-<p>Scrolling allows the user to navigate to content in the overflow using a swipe gesture. The
-scrolling speed is proportional to the speed of the gesture.</p>
-<h2 id="indicator">Scroll Indicator</h2>
-
-<p>Appears during scrolling to indicate what portion of the content is currently in view.</p>
-
-<div class="framed-nexus5-land-span-13">
-  <video class="play-on-hover" autoplay>
-    <source src="{@docRoot}design/media/scroll_indicator.mp4" type="video/mp4">
-    <source src="{@docRoot}design/media/scroll_indicator.webm" type="video/webm">
-    <source src="{@docRoot}design/media/scroll_indicator.ogv" type="video/ogg">
-  </video>
-</div>
-<div class="figure-caption">
-  <div class="video-instructions">&nbsp;</div>
-</div>
-
-<h2 id="index-scrolling">Index Scrolling</h2>
-
-<p>In addition to traditional scrolling, a long alphabetical list can also offer index scrolling: a way
-to quickly navigate to the items that begin with a particular letter. With index scrolling, a scroll
-indicator appears even when the user isn't scrolling. Touching or dragging it causes the current
-letter to pop up in a prominent way.</p>
-
-<div class="framed-nexus5-land-span-13">
-  <video class="play-on-hover" autoplay>
-    <source src="{@docRoot}design/media/scroll_index.mp4" type="video/mp4">
-    <source src="{@docRoot}design/media/scroll_index.webm" type="video/webm">
-    <source src="{@docRoot}design/media/scroll_index.ogv" type="video/ogg">
-  </video>
-</div>
-<div class="figure-caption">
-  <div class="video-instructions">&nbsp;</div>
-</div>
diff --git a/docs/html/design/building-blocks/seek-bars.jd b/docs/html/design/building-blocks/seek-bars.jd
deleted file mode 100644
index 04446d2..0000000
--- a/docs/html/design/building-blocks/seek-bars.jd
+++ /dev/null
@@ -1,45 +0,0 @@
-page.title=Seek Bars and Sliders
-page.tags=seekbar,progressbar
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/sliders.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Sliders<p>
-  </div>
-</a>
-
-<p>Interactive sliders make it possible to select a value from a continuous or discrete range of values
-by moving the slider thumb. The smallest value is to the left, the largest to the right. The
-interactive nature of the slider makes it a great choice for settings that reflect intensity levels,
-such as volume, brightness, or color saturation.</p>
-
-<div class="cols">
-  <div class="col-9">
-
-    <img src="{@docRoot}design/media/seekbar_example.png">
-
-  </div>
-  <div class="col-4">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4>Example</h4>
-<p>Interactive slider to set the ringer volume. The value can either be set through the hardware volume controls or interactively via a gesture.</p>
-
-  </div>
-</div>
-
-
-<div class="cols">
-  <div class="col-9">
-
-    <img src="{@docRoot}design/media/seekbar_style.png">
-    <div class="figure-caption">
-      Seek bars in Holo Light &amp; Dark
-    </div>
-
-  </div>
-  <div class="col-4">&nbsp;</div>
-</div>
diff --git a/docs/html/design/building-blocks/spinners.jd b/docs/html/design/building-blocks/spinners.jd
deleted file mode 100644
index 31c5558..0000000
--- a/docs/html/design/building-blocks/spinners.jd
+++ /dev/null
@@ -1,54 +0,0 @@
-page.title=Spinners
-page.tags=spinner,dropdown
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/menus.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Menus<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/spinner.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Spinners</p>
-  </div>
-</a>
-
-<p itemprop="description">Spinners provide a quick way to select one value from a set. In the default state, a spinner shows
-its currently selected value. Touching the spinner displays a dropdown menu with all other available
-values, from which the user can select a new one.</p>
-
-
-<div class="cols">
-  <div class="col-6">
-
-    <img src="{@docRoot}design/media/spinners_form.png">
-
-<h4>Spinners in forms</h4>
-<p>Spinners are useful for data picking in forms. They are compact and integrate nicely with other
-components. Use spinners in forms for both simple data input and in combination with other input
-fields. For example, a text field might let you edit an email address for a contact, while its
-associated spinner allows you to select whether it's a Home or Work address.</p>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/spinners_actionbar.png">
-
-<h4>Spinners in action bars</h4>
-<p>Use spinners in action bars to switch views. For example, Gmail uses a spinner to permit switching
-between accounts or commonly used labels. Spinners are useful when changing the view is important to
-your app, but not necessarily a frequent occurrence. In cases where view switching is frequent, use
-tabs.</p>
-
-  </div>
-</div>
-
-<img src="{@docRoot}design/media/spinners_hololightanddark.png">
-<div class="figure-caption">
-  Spinners in the Holo Dark and Holo Light themes, in various states.
-</div>
-
diff --git a/docs/html/design/building-blocks/switches.jd b/docs/html/design/building-blocks/switches.jd
deleted file mode 100644
index 9dd09ca..0000000
--- a/docs/html/design/building-blocks/switches.jd
+++ /dev/null
@@ -1,64 +0,0 @@
-page.title=Switches
-page.tags=switch,checkbox,radiobutton,button
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/selection-controls.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Selection Controls<p>
-  </div>
-</a>
-
-<p>Switches allow the user to select options. There are three kinds of switches: checkboxes, radio
-buttons, and on/off switches.</p>
-
-
-
-<h2 id="checkboxes">Checkboxes</h2>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/checkbox.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Checkboxes</p>
-  </div>
-</a>
-
-<p itemprop="description">Checkboxes allow the user to select multiple options from a set. Avoid using a single checkbox to
-turn an option off or on. Instead, use an on/off switch.</p>
-
-  <img src="{@docRoot}design/media/switches_checkboxes.png">
-
-
-
-<h2 id="radio-buttons">Radio Buttons</h2>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/radiobutton.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Radio Buttons</p>
-  </div>
-</a>
-
-<p>Radio buttons allow the user to select one option from a set. Use radio buttons for exclusive
-selection if you think that the user needs to see all available options side-by-side. Otherwise,
-consider a spinner, which uses less space.</p>
-
-  <img src="{@docRoot}design/media/switches_radios.png">
-
-
-
-<h2 id="switches">On/off Switches</h2>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/togglebutton.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Toggle Buttons</p>
-  </div>
-</a>
-
-<p>On/off switches toggle the state of a single settings option.</p>
-
-  <img src="{@docRoot}design/media/switches_switches.png">
-
-
diff --git a/docs/html/design/building-blocks/tabs.jd b/docs/html/design/building-blocks/tabs.jd
deleted file mode 100644
index 1315a2f..0000000
--- a/docs/html/design/building-blocks/tabs.jd
+++ /dev/null
@@ -1,65 +0,0 @@
-page.title=Tabs
-page.tags=tabs,actionbar,navigation,viewpager
-@jd:body
-
-<img src="{@docRoot}design/media/tabs_overview.png">
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/tabs.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Tabs<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}training/implementing-navigation/lateral.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Creating Swipe Views<br>with Tabs</p>
-  </div>
-</a>
-
-<p itemprop="description">Tabs in the action bar make it easy to explore and switch between different views or functional
-aspects of your app, or to browse categorized data sets.</p>
-
-<p>For details on using gestures to move between tabs, see the <a href="{@docRoot}design/patterns/swipe-views.html">Swipe Views</a> pattern.</p>
-
-<h2 id="scrollable">Scrollable Tabs</h2>
-
-
-<div class="cols">
-  <div class="col-6">
-
-<p>Scrolling tab controls can contain a larger number of items than a standard tab control. To navigate
-to the next/previous view, swipe left or right.</p>
-
-  </div>
-  <div class="col-7">
-
-    <video width="400" class="with-shadow play-on-hover" autoplay>
-      <source src="{@docRoot}design/media/tabs_scrolly.mp4" type="video/mp4">
-      <source src="{@docRoot}design/media/tabs_scrolly.webm" type="video/webm">
-      <source src="{@docRoot}design/media/tabs_scrolly.ogv" type="video/ogg">
-    </video>
-    <div class="figure-caption">
-      Scrolling tabs in the Play Store app.
-      <div class="video-instructions-image">&nbsp;</div>
-    </div>
-
-  </div>
-</div>
-
-
-<h2 id="fixed">Fixed Tabs</h2>
-<p>Fixed tabs display all items concurrently. To navigate to a different view, touch the tab, or swipe left or right.</p>
-<p>Fixed tabs are displayed with equal width, based on the width of the widest tab label. If there is insufficient room to display all tabs, the tab labels themselves will be scrollable. For this reason, fixed tabs are best suited for displaying 3 or fewer tabs.</p>
-
-<img src="{@docRoot}design/media/tabs_standard.png">
-<div class="figure-caption">
-  Tabs in Holo Dark &amp; Light.
-</div>
-
-<img src="{@docRoot}design/media/tabs_youtube.png">
-<div class="figure-caption">
-  Tabs in the Google Play Movies app.
-</div>
diff --git a/docs/html/design/building-blocks/text-fields.jd b/docs/html/design/building-blocks/text-fields.jd
deleted file mode 100644
index 9403679..0000000
--- a/docs/html/design/building-blocks/text-fields.jd
+++ /dev/null
@@ -1,88 +0,0 @@
-page.title=Text Fields
-page.tags=text,edittext,input
-@jd:body
-
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/components/text-fields.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Text Fields<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/controls/text.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Text Fields</p>
-  </div>
-</a>
-
-<p itemprop="description">Text fields allow the user to type text into your app. They can be either single line or multi-line.
-Touching a text field places the cursor and automatically displays the keyboard. In addition to
-typing, text fields allow for a variety of other activities, such as text selection (cut, copy,
-paste) and data lookup via auto-completion.</p>
-
-
-<div class="cols">
-  <div class="col-12">
-
-    <img src="{@docRoot}design/media/text_input_singlevsmultiline.png">
-
-  </div>
-</div>
-
-<h4>Single line and multi line</h4>
-<p>Single-line fields automatically scroll their content to the left as the text input cursor reaches
-the right edge of the input field. Multi-line text fields automatically break to a new line for
-overflow text and scroll vertically when the cursor reaches the lower edge.</p>
-
-<img src="{@docRoot}design/media/text_input_typesandtypedown.png">
-
-<div class="cols">
-  <div class="col-6">
-
-<h4>Text field types</h4>
-<p>Text fields can have different types, such as number, message, or email address. The type determines
-what kind of characters are allowed inside the field, and may prompt the virtual keyboard to
-optimize its layout for frequently used characters.</p>
-
-  </div>
-  <div class="col-6">
-
-<h4>Auto-complete text fields</h4>
-<p>Use auto-complete text fields to present real-time completions or search results in popups, so users
-can enter information more accurately and efficiently.</p>
-
-  </div>
-</div>
-
-<h2 id="text-selection">Text Selection</h2>
-
-<p>Users can select any word in a text field with a long press. This action triggers a text selection
-mode that facilitates extending the selection or choosing an action to perform on the selected text.
-Selection mode includes:</p>
-
-<div class="cols">
-  <div class="col-9">
-
-    <img src="{@docRoot}design/media/text_input_textselection.png">
-
-  </div>
-  <div class="col-4 with-callouts">
-
-<ol>
-<li>
-<h4>Contextual action bar</h4>
-<p>A contextual action bar (CAB) displays the actions available to perform on the selection:
- typically cut, copy, and paste, but apps can insert additional commands as needed.</p>
-</li>
-<li>
-<h4>Selection handles</h4>
-<p>Selection handles can be dragged to select more or less text while remaining in selection mode.</p>
-</li>
-</ol>
-
-  </div>
-</div>
-
diff --git a/docs/html/design/design_toc.cs b/docs/html/design/design_toc.cs
index 63f5cad..85569ef 100644
--- a/docs/html/design/design_toc.cs
+++ b/docs/html/design/design_toc.cs
@@ -1,15 +1,15 @@
 <ul id="nav">
 
   <li class="nav-section">
-    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/index.html">Get Started</a></div>
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/get-started/creative-vision.html">Creative Vision</a></div>
     <ul>
-      <li><a href="<?cs var:toroot ?>design/get-started/creative-vision.html">Creative Vision</a></li>
       <li><a href="<?cs var:toroot ?>design/get-started/principles.html">Design Principles</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/new.html">New in Android</a></li>
     </ul>
   </li>
 
   <li class="nav-section">
-    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>design/material/index.html">Material Design</a></div>
+    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>design/material/index.html">Material for Android</a></div>
   </li>
 
   <li class="nav-section">
@@ -43,59 +43,20 @@
   </li>
 
   <li class="nav-section">
-    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/style/index.html">Style</a></div>
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/style/index.html">Pure Android</a></div>
     <ul>
       <li><a href="<?cs var:toroot ?>design/style/devices-displays.html">Devices and Displays</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/themes.html">Themes</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/touch-feedback.html">Touch Feedback</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/metrics-grids.html">Metrics and Grids</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/typography.html">Typography</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/color.html">Color</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/iconography.html">Iconography</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/branding.html">Your Branding</a></li>
-      <li><a href="<?cs var:toroot ?>design/style/writing.html" zh-cn-lang="写作风格">Writing Style</a></li>
-    </ul>
-  </li>
-
-  <li class="nav-section">
-    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></div>
-    <ul>
-      <li><a href="<?cs var:toroot ?>design/patterns/new.html">New in Android</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/gestures.html">Gestures</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/app-structure.html">App Structure</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/navigation.html">Navigation</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/actionbar.html">Action Bar</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/navigation-drawer.html">Navigation Drawer</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/swipe-views.html">Swipe Views</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/fullscreen.html">Full Screen</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/selection.html">Selection</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/confirming-acknowledging.html">Confirming &amp; Acknowledging</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/notifications.html">Notifications</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/widgets.html">Widgets</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/settings.html">Settings</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/help.html">Help</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/swipe-views.html">Swipe Views</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/fullscreen.html">Full Screen</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/confirming-acknowledging.html">Confirming &amp; Acknowledging</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/pure-android.html">Pure Android</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/compatibility.html">Compatibility</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/accessibility.html">Accessibility</a></li>
-      <li><a href="<?cs var:toroot ?>design/patterns/pure-android.html">Pure Android</a></li>
-    </ul>
-  </li>
-
-  <li class="nav-section">
-    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></div>
-    <ul>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/tabs.html">Tabs</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/lists.html">Lists</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/grid-lists.html">Grid Lists</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/scrolling.html">Scrolling</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/spinners.html">Spinners</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/buttons.html">Buttons</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/text-fields.html">Text Fields</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/seek-bars.html">Seek Bars</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/progress.html">Progress &amp; Activity</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/switches.html">Switches</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/dialogs.html">Dialogs</a></li>
-      <li><a href="<?cs var:toroot ?>design/building-blocks/pickers.html">Pickers</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/help.html">Help</a></li>
     </ul>
   </li>
 
@@ -103,8 +64,8 @@
     <div class="nav-section-header empty"><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></div>
   </li>
 
-  <li class="nav-section">
+<!-- <li class="nav-section">
     <div class="nav-section-header empty"><a href="<?cs var:toroot ?>design/videos/index.html">Videos</a></div>
-  </li>
+  </li> -->
 
 </ul>
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index 0b9f59f..089a4af 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -3,107 +3,16 @@
 @jd:body
 
 
-<p>You may use these materials without restriction to facilitate your app design
-and implementation.</p>
+<p>For icons, sticker sheets, and other downloadable resources, visit the
+<a href="http://www.google.com/design">Design site</a> or use the links below. </p>
 
-
-<h2 id="stencils">Phone &amp; Tablet Stencils</h2>
-
-<div class="cols">
-  <div class="col-5">
-
-
-<p>Drag and drop your way to beautifully designed Android apps. The stencils feature the
-rich typography, colors, interactive controls, and icons found throughout Android, along with
-phone and tablet outlines to frame your creations. Source files for icons and controls are also
-available.</p>
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/downloads_stencils.png">
-
-  </div>
-
-  <div class="col-4">
-    <a class="notice-designers-material"
-      style="width:218px;"
-      href="http://www.google.com/design/spec/resources/layout-templates.html">
-      <div>
-        <h3>Material Design</h3>
-        <p>Layout Templates<p>
-      </div>
-    </a>
-  </div>
-
-  <div class="col-4">
-    <a class="notice-designers-material"
-      style="width:218px;"
-      href="http://www.google.com/design/spec/resources/sticker-sheets-icons.html">
-      <div>
-        <h3>Material Design</h3>
-        <p>Sticker Sheets<p>
-      </div>
-    </a>
-  </div>
-
-  <div class="col-4">
-<p>
-  <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Photoshop Sources');"
-    href="{@docRoot}downloads/design/Android_Design_Stencils_Sources_20131106.zip">Adobe&reg; Photoshop&reg; Stencils and Sources</a>
-</p>
-
-  </div>
+  <div class="resource-widget resource-flow-layout col-16"
+       data-query="collection:design/landing/resources"
+       data-cardSizes="6x2"
+       data-maxResults="6"></div>
 </div>
 
 
-
-
-
-
-<h2 id="action-bar-icon-pack">Action Bar Icon Pack</h2>
-
-<div class="cols">
-  <div class="col-5">
-
-<p>Action bar icons are graphic buttons that represent the most important actions people can take
-within your app. <a href="{@docRoot}design/style/iconography.html">More on Action Bar Iconography</a></p>
-<p>The download package includes icons that are scaled for various screen densities and suitable for
-use with the Holo Light and Holo Dark themes. The package also includes unstyled icons that you can
-modify to match your theme, plus source files.</p>
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_actionbar_style.png">
-
-  </div>
-
-  <div class="col-4">
-    <a class="notice-designers-material"
-      style="width:218px;"
-      href="http://www.google.com/design/spec/resources/sticker-sheets-icons.html">
-      <div>
-        <h3>Material Design</h3>
-        <p>Sticker Sheets<p>
-      </div>
-    </a>
-  </div>
-
-  <div class="col-4">
-
-<p>
-  <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Action Bar Icons');"
-    href="{@docRoot}downloads/design/Android_Design_Icons_20131106.zip">Action Bar Icon Pack</a>
-</p>
-
-  </div>
-</div>
-
-
-
-
-
 <h2 id="Wear">Android Wear Materials</h2>
 
 <div class="cols">
@@ -243,86 +152,4 @@
   <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Wear Watch Face Example Specifications');"
     href="{@docRoot}downloads/design/Slide_IconExample.psd">Adobe&reg; Photoshop&reg; Icon</a>
   </div>
-</div>
-
-
-
-
-<h2 id="style">Style</h2>
-
-<div class="cols">
-  <div class="col-5">
-
-<h4 id="roboto">Roboto</h4>
-<p>Ice Cream Sandwich introduced a new type family named Roboto, created specifically for the
-requirements of UI and high-resolution screens.</p>
-<p>For Android Wear, Roboto Condensed is the system font and the Regular and Light variants should be used by all Wear apps.</p>
-<p><a href="{@docRoot}design/style/typography.html">More on Roboto</a></p>
-<p><a href="http://www.google.com/fonts/specimen/Roboto" class="external-link">Roboto on Google Fonts</a></p>
-<p><a href="http://www.google.com/fonts/specimen/Roboto+Condensed" class="external-link">Roboto Condensed on Google Fonts</a></p>
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/downloads_roboto_specimen_preview.png">
-
-  </div>
-
-  <div class="col-4">
-    <a class="notice-designers-material"
-      style="width:218px;"
-      href="http://www.google.com/design/spec/resources/roboto-noto-fonts.html">
-      <div>
-        <h3>Material Design</h3>
-        <p>Roboto Font<p>
-      </div>
-    </a>
-  </div>
-
-  <div class="col-4">
-
-<p>
-  <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Roboto ZIP');"
-    href="{@docRoot}downloads/design/roboto-1.2.zip">Roboto</a>
-  <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Roboto Specemin Book');"
-    href="{@docRoot}downloads/design/Roboto_Specimen_Book_20131031.pdf">Specimen Book</a>
-</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-5">
-
-<h4>Color</h4>
-<p>In Android's color palette, each color has a corresponding darker
-shade that can be used as a complement when needed.</p>
-<p><a href="{@docRoot}design/style/color.html">More on Color</a></p>
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/downloads_color_swatches.png">
-
-  </div>
-
-  <div class="col-4">
-    <a class="notice-designers-material"
-      style="width:218px;"
-      href="http://www.google.com/design/spec/resources/color-palettes.html">
-      <div>
-        <h3>Material Design</h3>
-        <p>Color Palettes<p>
-      </div>
-    </a>
-  </div>
-
-  <div class="col-4">
-
-<p>
-  <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Color Swatches');"
-    href="{@docRoot}downloads/design/Android_Design_Color_Swatches_20120229.zip">Color Swatches</a>
-</p>
-
-  </div>
-</div>
+</div>
\ No newline at end of file
diff --git a/docs/html/design/get-started/creative-vision.jd b/docs/html/design/get-started/creative-vision.jd
index 3955494..974d5d0 100644
--- a/docs/html/design/get-started/creative-vision.jd
+++ b/docs/html/design/get-started/creative-vision.jd
@@ -7,10 +7,9 @@
 <div class="vspace size-1">&nbsp;</div>
 
 <p itemprop="description">
-  Starting with Ice Cream Sandwich, we focused the design of
-  Android around these three overarching goals, which apply
-  to our core apps as well as the system at large.
-  As you work with Android, consider these goals.
+  Android design is shaped by three overarching goals for users that apply
+  to apps as well as the system at large. As you work with Android,
+  keep these goals in mind.
 </p>
 
 <div class="vspace size-1">&nbsp;</div>
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
index 74af6e7..638f35b 100644
--- a/docs/html/design/index.jd
+++ b/docs/html/design/index.jd
@@ -14,17 +14,14 @@
         <img class="dac-hero-image" src="/design/media/hero-material-design.png">
       </div>
       <div class="col-1of2 col-pull-1of2">
-        <h1 class="dac-hero-title">Up and running with Material Design</h1>
+        <h1 class="dac-hero-title">Up and running with material design</h1>
         <p class="dac-hero-description">
-          Android 5.0 introduces a design metaphor inspired by paper and ink that provides a reassuring sense of tactility.
+        Android uses a new design metaphor inspired by paper and ink that provides a reassuring
+        sense of tactility. Visit the <a href="http://www.google.com/design/spec/material-design/introduction">material design</a> site for more resources. 
         </p>
         <a class="dac-hero-cta" href="https://www.google.com/design/spec/material-design/introduction.html">
           <span class="dac-sprite dac-auto-chevron"></span>
-          Introducing Material Design
-        </a><br>
-        <a class="dac-hero-cta" href="/design/material/index.html">
-          <span class="dac-sprite dac-auto-chevron"></span>
-          Material Design for Android
+          Introducing material design
         </a><br>
         <a class="dac-hero-cta" href="https://www.google.com/design/spec/resources/color-palettes.html">
           <span class="dac-sprite dac-auto-chevron"></span>
@@ -56,7 +53,7 @@
 <section class="dac-section dac-light"><div class="wrap">
   <h1 class="dac-section-title">Pure Android</h1>
   <div class="dac-section-subtitle">
-    This is a place holder paragraph. Some text here would povide some context.
+    Design around Android's capabilities and conventions to give users the best experience.
   </div>
   <div class="resource-widget resource-flow-layout col-16"
        data-query="collection:design/landing/pureandroid"
@@ -67,7 +64,7 @@
 <section class="dac-section dac-gray"><div class="wrap">
   <h1 class="dac-section-title">Resources</h1>
   <div class="dac-section-subtitle">
-    This is a place holder paragraph. Some text here would povide some context.
+    Essential downloads, stencils, and tools to help you create your design.
   </div>
   <div class="resource-widget resource-flow-layout col-16"
        data-query="collection:design/landing/resources"
diff --git a/docs/html/design/patterns/gestures.jd b/docs/html/design/patterns/gestures.jd
deleted file mode 100644
index b471ee3..0000000
--- a/docs/html/design/patterns/gestures.jd
+++ /dev/null
@@ -1,135 +0,0 @@
-page.title=Gestures
-page.tags=gesture,input,touch
-@jd:body
-
-<a class="notice-designers-material"
-   href="http://www.google.com/design/spec/patterns/gestures.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Gestures<p>
-  </div>
-</a>
-
-<p>Gestures allow users to interact with your app by manipulating the screen objects you provide. The
-following table shows the core gesture set that is supported in Android.</p>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_touch.png">
-    <h4>Touch</h4>
-    <p>Triggers the default functionality for a given item.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>Press, lift</p></li>
-    </ul>
-  </div>
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_longtouch.png">
-    <h4>Long press</h4>
-    <p>Enters data selection mode. Allows you to select one or more items in a view and act upon
-    the data using a contextual action bar. Avoid using long press for showing contextual menus.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>Press, wait, lift</p></li>
-    </ul>
-  </div>
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_swipe.png">
-    <h4>Swipe or drag</h4>
-    <p>Scrolls overflowing content, or navigates between views in the same hierarchy. Swipes are
-    quick and affect the screen even after the finger is picked up. Drags are slower and more precise,
-    and the screen stops responding when the finger is picked up.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>Press, move, lift</p></li>
-    </ul>
-  </div>
-
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_drag.png">
-    <h4>Long press drag</h4>
-    <p>Rearranges data within a view, or moves data into a container (e.g. folders on Home Screen).</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>Long press, move, lift</p></li>
-    </ul>
-  </div>
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_doubletouch.png">
-    <h4>Double touch </h4>
-    <p> Scales up a standard amount around the target with each repeated gesture until reaching
-    maximum scale. For nested views, scales up the smallest targetable view, or returns it to
-    its original scale. Also used as a secondary gesture for text selection.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>Two touches in quick succession</p>
-      </li>
-    </ul>
-  </div>
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_doubletouchdrag.png">
-    <h4>Double touch drag</h4>
-    <p>Scales content by pushing away or pulling closer, centered around gesture.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>A single touch followed in quick succession by a drag up or down:</p>
-        <ul style="padding-left:1.5em;list-style-type:disc;">
-          <li>Dragging up decreases content scale</li>
-          <li>Dragging down increases content scale</li>
-          <li>Reversing drag direction reverses scaling.</li>
-        </ul>
-      </li>
-    </ul>
-  </div>
-
-</div>
-
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_pinchopen.png" style="margin-left:-4px">
-    <h4>Pinch open</h4>
-    <p>Zooms into content.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>2-finger press, move outwards, lift</p></li>
-    </ul>
-  </div>
-
-  <div class="col-4">
-    <img src="{@docRoot}design/media/gesture_pinchclose.png">
-    <h4>Pinch close</h4>
-    <p>Zooms out of content.</p>
-    <ul>
-      <li class="no-bullet with-icon action">
-        <h4>Action</h4>
-        <p>2-finger press, move inwards, lift</p>
-      </li>
-    </ul>
-  </div>
-
-</div>
-
diff --git a/docs/html/design/patterns/index.jd b/docs/html/design/patterns/index.jd
deleted file mode 100644
index e091a29..0000000
--- a/docs/html/design/patterns/index.jd
+++ /dev/null
@@ -1,30 +0,0 @@
-page.title=Patterns
-header.justLinks=1
-footer.hide=1
-@jd:body
-
-<style>
-#landing-graphic-container {
-  position: relative;
-}
-
-#text-overlay {
-  position: absolute;
-  left: 0;
-  top: 492px;
-  width: 200px;
-}
-</style>
-
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    <span itemprop="description">Design apps that behave in a consistent, predictable
-    fashion.</span>
-    <br><br>
-    <a href="{@docRoot}design/patterns/new.html" class="landing-page-link">New in Android</a>
-  </div>
-
-  <a href="{@docRoot}design/patterns/new.html">
-    <img src="{@docRoot}design/media/patterns_landing.png">
-  </a>
-</div>
diff --git a/docs/html/design/patterns/multi-pane-layouts.jd b/docs/html/design/patterns/multi-pane-layouts.jd
deleted file mode 100644
index c9d3d84..0000000
--- a/docs/html/design/patterns/multi-pane-layouts.jd
+++ /dev/null
@@ -1,130 +0,0 @@
-page.title=Multi-pane Layouts
-page.tags="tablet","navigation","layout","fragment"
-page.metaDescription=Design guide with examples of how to flatten navigation and provide improved layout across the range of Android devices.
-
-@jd:body
-
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/layout/structure.html#structure-ui-regions">
-  <div>
-    <h3>Material Design</h3>
-    <p>UI Regions and Guidance<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}training/basics/fragments/index.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Building a Dynamic UI with Fragments</p>
-  </div>
-</a>
-
-<p>When writing an app for Android, keep in mind that Android devices
-come in many different screen sizes and types. Make sure that your app consistently provides a
-balanced and aesthetically pleasing layout by adjusting its content to varying screen sizes and
-orientations.</p>
-
-<p><em>Panels</em> are a great way for your app to achieve this. They allow you to combine multiple views into
-one compound view when a lot of horizontal screen real estate is available and by splitting them up
-when less space is available.</p>
-<h2 id="combining-views">Combining Multiple Views Into One</h2>
-
-<p>On smaller devices your content is typically divided into a master grid or list view and a detail
-view. Touching an item in the master view opens a different screen showing that item's detail
-information.</p>
-
-<img src="{@docRoot}design/media/multipane_views.png">
-
-<p>Because tablets have more screen real estate than phones, you can use panels to combine the related
-list and detail views into a single compound view. This uses the additional space more efficiently
-and makes navigating the app easier. </p>
-
-<img src="{@docRoot}design/media/multipane_view_tablet.png">
-
-<p>In general, use the pane on the right to present more information about the item you selected in the
-left pane. Make sure to keep the item in the left pane selected in order to establish the
-relationship between the panels.</p>
-<h2 id="orientation">Compound Views and Orientation Changes</h2>
-
-<p>Screens should strive to have the same functionality regardless of orientation. If you use a compound view in
-one orientation, try not to split it up when the user rotates the screen. There are several techniques
-you can use to adjust the layout after orientation change while keeping functional parity intact.</p>
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/multipane_stretch.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Stretch/compress</h4>
-<p>Adjust the column width of your left pane to achieve a balanced layout in both orientations.</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/multipane_stack.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Stack</h4>
-<p>Rearrange the panels on your screen to match the orientation.</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/multipane_expand.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Expand/collapse</h4>
-<p>When the device rotates, collapse the left pane view to only show the most important information.</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/multipane_show.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Show/hide</h4>
-<p>If your screen cannot accommodate the compound view on rotation show the right pane in full screen view on rotation to portrait. Use the Up icon in action bar to show the parent screen.</p>
-
-  </div>
-</div>
-
-
-
-
-<h2 id="checklist">Checklist</h2>
-
-<ul>
-<li>
-<p>Plan in advance on how your app scales to different screen sizes and screen orientations.</p>
-</li>
-<li>
-<p>Identify the most appropriate method for the panels in your compound views to reorganize
-  themselves when screen orientation changes.</p>
-</li>
-<li>
-<p>Look for opportunities to consolidate your views into multi-panel compound views.</p>
-</li>
-<li>
-<p>Make sure that your screens try to provide functional parity after the screen orientation
-  changes.</p>
-</li>
-</ul>
diff --git a/docs/html/design/patterns/navigation-drawer.jd b/docs/html/design/patterns/navigation-drawer.jd
deleted file mode 100644
index b359470..0000000
--- a/docs/html/design/patterns/navigation-drawer.jd
+++ /dev/null
@@ -1,346 +0,0 @@
-page.title=Navigation Drawer
-page.tags=DrawerLayout,SlidingPaneLayout
-@jd:body
-
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/layout/structure.html#structure-side-nav">
-  <div>
-    <h3>Material Design</h3>
-    <p>Side Nav<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}training/implementing-navigation/nav-drawer.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Creating a Navigation Drawer</p>
-  </div>
-</a>
-
-
-<p>The navigation drawer is a panel that transitions in from the left edge of the screen and
-displays the app’s main navigation options.</p>
-
-
-<h4>Displaying the navigation drawer</h4>
-
-<p>The user can bring the navigation drawer onto the screen by swiping from the left edge of the
-screen or by touching the application icon on the action bar.</p>
-
-<p>As the navigation drawer expands, it overlays the content but not the action bar. When the
-drawer is fully extended, the action bar adjusts its content by replacing the current action
-bar title with the app name and removing all actions that are contextual to the view underneath
-the navigation drawer. The overflow menu with the standard action items for Settings and Help
-remains visible.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_overview.png">
-<div class="figure-caption">
-  The user can open the drawer panel by touching the navigation drawer indicator.
-</div>
-
-<p>Because they are transient, navigation drawers make views less cluttered. You can also use
-them at deeper levels in the navigation hierarchy, allowing users to switch to your app's most
-important screens from anywhere in the app.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_open_from_lower.png">
-<div class="figure-caption">
-  Open the drawer from anywhere in your app by swiping from the left edge of the screen.
-</div>
-
-
-<h4>Dismissing the navigation drawer</h4>
-
-<p> When the navigation drawer is expanded, the user can dismiss it in one of four ways: </p>
-<ul>
-  <li>Touching the content outside the navigation drawer</li>
-  <li>Swiping to the left anywhere on the screen (including edge swipe from right)</li>
-  <li>Touching the app icon/title in the action bar</li>
-  <li>Pressing Back</li>
-</ul>
-
-
-<h2 id="WhenToUse"> When to Use the Navigation Drawer </h2>
-
-<p> The navigation drawer is not a general replacement for top-level navigation via spinners
-or tabs. The structure of your app should guide your choice of which pattern to use for
-top-level switching. For more information on top-level switching mechanisms, see the
-<a href="{@docRoot}design/patterns/app-structure.html">Application Structure</a> design pattern.</p>
-<p> Here are some examples of where navigation drawers work best:</p>
-
-<h4>More than 3 top-level views</h4>
-<p> Navigation drawers are great for displaying a large number of navigation targets
-concurrently. Use the navigation drawer if you have more than 3 unique top-level views.
-If not, use fixed tabs for top-level organization to ease discovery and interaction.</p>
-
-<h4>Cross-navigation from lower levels</h4>
-<p> If your app requires cross-navigating between lower-level screens, consider using the
-navigation drawer. Because it is accessible from anywhere in the app, the drawer enables
-efficient navigation from lower-level screens to other important places in your app.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_cross_nav.png">
-<div class="figure-caption">
-  The navigation drawer makes cross-navigation at lower levels possible.
-</div>
-
-
-<h4>Deep navigation branches</h4>
-<p> If you have particularly deep branches, navigating to the top-level of your app can become
-repetitive and cumbersome with Up and Back alone. Since navigation drawers are accessible from
-anywhere in the app, navigation up to the top level is faster and more efficient.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_quick_to_top.png">
-<div class="figure-caption">
-  The navigation drawer allows for quick jumps to the top-level of your app, removing the need
-  for repetitive Back or Up sequences.
-</div>
-
-
-<h2 id="Hubs">Navigation Hubs</h2>
-
-<p>The navigation drawer is a reflection of your app’s structure and displays its major
-navigation hubs. Think of navigation hubs as those places in your app that a user will want
-to visit frequently or use as a jumping-off point to other parts of the app.
-At a minimum, the navigation hubs are the top-level views, since they correspond to your app’s
-major functional areas.</p>
-<p> If your app’s structure is deep, you can add screens from lower levels that your users will
-likely visit often and make those navigation hubs as well.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_navigation_hubs.png">
-<div class="figure-caption">
-  The navigation drawer contains all of your app's navigation hubs. Include your top level
-  screens as well as important lower-level screens.
-</div>
-
-<div class="cols">
-  <div class="col-8">
-  <p> To facilitate access to the navigation drawer on navigation hubs, all screens that
-  correspond to an entry in your navigation drawer should show the navigation drawer indicator
-  next to the application icon in the action bar. Touching the app icon causes the navigation
-  drawer to slide in from the left. </p>
-  <p> All other lower-level screens show the traditional Up indicator next to the application
-  icon. The drawer is still accessible with an edge-swipe, but is not featured in the action bar.</p>
-  </div>
-  <div class="col-5">
-    <img src="{@docRoot}design/media/navigation_drawer_indicator_big.png">
-    <div class="figure-caption">
-    App icon with navigation drawer indicator.
-  </div>
-  </div>
-</div>
-
-
-<h2 id="Content">Content of the Navigation Drawer</h2>
-
-<p> Keep the content of the navigation drawer focused on app navigation. Expose the navigation
-hubs of your app as list items inside the navigation drawer - one item per row.
-
-<div class="cols">
-  <div class="col-8">
-  <h4>Titles, icons, and counters</h4>
-  <p> You can structure navigation targets by adding titles. The titles are not interactive,
-  but just organize navigation targets into functional topics. If you have many navigation
-  targets, use titles to orient the user within the drawer.</p>
-  <p> Navigation targets can have optional leading icons as well as trailing counters. Use
-  the counters to inform users about a changed state of data in the corresponding view.</p>
-  </div>
-  <div class="col-5">
-  <img src="{@docRoot}design/media/navigation_drawer_titles_icons.png">
-  <div class="figure-caption">
-    Use titles and icons to organize your drawer.
-  </div>
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-8">
-  <img src="{@docRoot}design/media/navigation_drawer_collapse.png">
-  <div class="figure-caption">
-    Collapsible navigation items are split. Use the left side for navigation and the right
-    to collapse and expand items.
-    </div>
-  </div>
-  <div class="col-5">
-  <h4>Collapsible navigation items</h4>
-  <p>If you have many views with some subordinate to others, consider collapsing them into one
-  expandable item to conserve space.
-  The parent in the navigation drawer then turns into a split item. The left side allows
-  navigation to the parent item’s view, and the right side collapses or expands the list of
-  child items. </p>
-  <p> At launch, the initial state of the collapsible items is up to you. As a rule, all
-  top-level view entries of the navigation drawer should be visible. If you have many collapsible
-  items, consider collapsing all items to allow the user to see the top-level views in their
-  entirety.</p>
-  <p> When the user opens the drawer from a lower-level screen, expand the associated branch
-  of the top-level view to give a stronger sense of place and highlight navigation opportunities
-  close to the user’s current
-  location in the app.</p>
-  </div>
-</div>
-
-
-<h2 id="ActionBar">Navigation Drawers and Action Bars</h2>
-
-<p> When the user expands the navigation drawer, the task focus switches to selecting an item
-from the drawer. Because the drawer does not overlay the action bar, users may not realize that
-the items in the action bar do not pertain to the navigation drawer. </p>
-<p> To reduce confusion, adjust the content of the action bar to the following, once the drawer
-is fully expanded:</p>
-<ul>
-  <li>App icon</li>
-  <li>App name</li>
-  <li>Remove actions from the action bar that are contextual to the underlying view (such as
-  Create new, Refresh). You may retain actions with global scope, such as “Search”.</li>
-  <li>Overflow menu with expected navigation targets, such as Settings and Help.</li>
-</ul>
-
-<img src="{@docRoot}design/media/navigation_drawer_open_overflow.png">
-<div class="figure-caption">
-  Clean up the action bar when the drawer is fully expanded. Remove actions that are not needed
-  and display your app's name in the title area.
-</div>
-
-<h4>Actions</h4>
-<div class="cols">
-  <div class="col-6">
-  <img src="{@docRoot}design/media/navigation_drawer_nav_and_actions.png">
-    <div class="figure-caption">
-    Keep actions on the right side of the action bar and in the overflow
-  </div>
-  </div>
-  <div class="col-6">
-  <p> Don’t place actions in the navigation drawer. Actions belong in the action bar, and the
-  user expects to see them there. Keep in mind that not all applications use the navigation
-  drawer pattern. It may be tempting to expose all your app’s capabilities in a single place,
-  but keep the bigger picture in mind. Place your actions where all apps display them.</p>
-  </div>
-</div>
-<div class="cols">
-  <div class="col-6">
-  <p> This also applies to common navigation targets, such as access to Help or the app’s
-  Settings. As per style guide convention Help and Settings are always located in the action
-  overflow.</p>
-  </div>
-  <div class="col-6">
-  <img src="{@docRoot}design/media/navigation_drawer_settings_help.png">
-    <div class="figure-caption">
-    Keep Help and Settings in the overflow.
-  </div>
-  </div>
-</div>
-
-
-<h4>Contextual action bars</h4>
-<p> Sometimes the user will be in a state where a contextual action bar (CAB) appears instead
-of the app’s action bar. This typically happens when the user selects text or selects multiple
-items after a press-and-hold gesture. While the CAB is visible, you should still allow the
-user to open the navigation drawer using an edge swipe. However, replace the CAB with the
-standard action bar while the navigation drawer is open. When the user dismisses the drawer,
-re-display the CAB.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_CAB.png">
-<div class="figure-caption">
-  Hide contextual action bars while the drawer is visible.
-</div>
-
-<p>If the user navigates away from a view with selected content, deselect the content before
-before navigating to the new view.</p>
-
-
-<h2 id="Interaction">Interaction Details</h2>
-
-<h4>Introduce the user to the drawer at first use</h4>
-<p> Upon first launch of your app, introduce the user to the navigation drawer by
-automatically opening it. This ensures that users know about the navigation drawer and prompts
-them to learn about the structure of your app by exploring its content. Continue showing the
-drawer upon subsequent launches until the user actively expands the navigation drawer manually.
-Once you know that the user understands how to open the drawer, launch the app with the
-navigation drawer closed. </p>
-
-<img src="{@docRoot}design/media/navigation_drawer_first_run.png">
-<div class="figure-caption">
-  At first use, show the navigation drawer automatically to help the user learn the
-  functionality and structure of your app.
-</div>
-
-<h4>Give the user a quick peek</h4>
-<p> If the user touches the very left edge of the screen (within 20 dp from the left), have the
-drawer peek out as soon as the finger makes contact with the display. This promotes accidental
-discovery and provides richer feedback. </p>
-
-<img src="{@docRoot}design/media/navigation_drawer_peek.png">
-<div class="figure-caption">
-  The navigation drawer peeks out when the user touches the very left edge of the screen.
-</div>
-
-<h4>Highlights</h4>
-<p> When you open the navigation drawer from a screen that is represented inside the drawer,
-highlight its entry in the drawer. Vice versa, if you open the drawer from a screen that is
-not listed in the drawer, none of the items of the drawer should be highlighted.</p>
-
-
-<h2 id="ImpactOnNav">Impact of Drawer on Overall App Navigation</h2>
-
-<p>The navigation drawer is an alternative to other top-level navigation patterns. To make apps
-with navigation drawers work consistently with apps that use a tab or spinner pattern, remember
-that all navigation requirements for system Back and Up apply.</p>
-<p>Pay special attention to the following situations:</p>
-
-<h4>System Back at the top level of the app</h4>
-<p>Touching System Back at the app’s top level never opens the navigation drawer. Instead,
-System Back behaves according to the navigation rules for the top level, such as navigating
-to the previous app within the task or navigating to the Home screen.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_top_out.png">
-<div class="figure-caption">
-  System Back does not show the drawer, but behaves according to the navigation rules for
-  the top level.
-</div>
-
-<h4>System Back after cross navigation to lower hierarchy levels</h4>
-<p>If the user navigates to a lower hierarchy screen from the navigation drawer and the screen
-has a direct parent, then the Back stack is reset and Back points to the target screen’s parent.
-This Back behavior is the same as when a user navigates into an app from a notification.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_reset_backstack.png">
-<div class="figure-caption">
-  Reset the Back stack if your lower-level navigation target has direct parents.
-</div>
-
-
-<h2 id="Style">Style</h2>
-
-<p>The width of the navigation drawer depends on the content you want to display, but should be
-between a minimum of 240 dp and a maximum of 320 dp. The height of the individual line items
-should not fall below 48 dp. See the layout guideline below for recommendations on padding and
-spacing.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_layout.png">
-<div class="figure-caption">
-  Layout guidelines for the navigation drawer.
-</div>
-
-
-<p>Pick the drawer background to best match your app’s theme. See the following examples
-for a Holo light and a Holo dark themed drawer.</p>
-
-<img src="{@docRoot}design/media/navigation_drawer_holo_dark_light.png">
-<div class="figure-caption">
-  Navigation drawers in Holo light and Holo dark themed apps.
-</div>
-
-
-<h2 id="Checklist">Navigation Drawer Checklist</h2>
-
-<p>Even if you already support a similar navigation drawer, update your drawer to this
-pattern to make sure that:</p>
-<ul>
-  <li>The action bar remains in place and adjusts its content.</li>
-  <li>Your navigation drawer overlays the content.</li>
-  <li>Any view represented in the drawer has a navigation drawer indicator in its action bar
-  that allows the drawer to be opened by touching the app icon.</li>
-  <li>You take advantage of the new visual drawer transition.</li>
-  <li>Any view not represented in the drawer maintains the traditional Up indicator in its action bar.</li>
-  <li>You stay in sync with the general navigation patterns for Up and Back.</li>
-</ul>
-
diff --git a/docs/html/design/patterns/selection.jd b/docs/html/design/patterns/selection.jd
deleted file mode 100644
index e00f726..0000000
--- a/docs/html/design/patterns/selection.jd
+++ /dev/null
@@ -1,123 +0,0 @@
-page.title=Selection
-page.tags=actionmode,navigation,contextual
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/patterns/selection.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Selection<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/menus.html#context-menu">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Menus: Creating Contextual Menus</p>
-  </div>
-</a>
-
-
-<p>Android 3.0 changed the <em>long press</em> gesture&mdash;that is, a touch that's held in the same position for a moment&mdash;to be the global gesture to select data.. This affects the way you should
-handle multi-select and contextual actions in your apps.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-6">
-
-<h4>What has changed?</h4>
-<p>In previous versions of Android, the long press gesture was universally used to display contextual
-actions for a given data item in a contextual menu.</p>
-<p>This pattern changed with Android 3.0. The long press gesture is now used to select data, combining
-contextual actions and selection management functions for selected data into a new element called
-the contextual action bar (CAB).</p>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/selection_context_menu.png">
-    <div class="figure-caption">
-      Traditional use of the long press gesture to show contextual menus.
-    </div>
-
-  </div>
-</div>
-
-<h4>Using the contextual action bar</h4>
-<p itemprop="description">The contextual action bar (CAB) is a temporary action bar that overlays your app's current action bar while data
-is selected. It appears after the user long-presses on a selectable data item.</p>
-
-<img src="{@docRoot}design/media/selection_cab_big.png">
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-6">
-
-<p>From here the user can:</p>
-<ul>
-<li>Select additional data items by touching them.</li>
-<li>Trigger an action from the CAB that applies to all highlighted data items. The CAB then
-  automatically dismisses itself.</li>
-<li>Dismiss the CAB via the navigation bar's Back button or the CAB's checkmark button. This removes
-  the CAB along with all selection highlights.</li>
-</ul>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/selection_cab_example.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-6">
-
-<h4>Selecting CAB actions</h4>
-<p>You can decide which actions and elements appear in the CAB. Use the guidelines in the <a href="actionbar.html">Action Bar
-pattern</a> to decide which items to surface at the top level and which to move to the
-action overflow.</p>
-<h4>Dynamically adjust CAB actions</h4>
-<p>In most cases you need to adjust the actions in the CAB dynamically as the user adds more items to
-the selection. Actions that apply to a single selected data item don't necessarily apply to multiple
-selected data items of the same kind.</p>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/selection_adjusting_actions.png">
-    <div class="figure-caption">
-      Adjusting actions in the CAB as additional items are selected.
-    </div>
-
-  </div>
-</div>
-
-<div class="note develop">
-<p><strong>Developer Guide</strong></p>
-  <p>For information about how to create a contextual action bar, read
-  <a href="{@docRoot}guide/topics/ui/menus.html#CAB">Using the contextual action mode</a>.</p>
-</div>
-
-
-<h2 id="checklist">Checklist</h2>
-
-<ul>
-<li>
-<p>Whenever your app supports the selection of multiple data items, make use of the contextual action
-  bar (CAB).</p>
-</li>
-<li>
-<p>Reserve the long press gesture for selection exclusively. Don't use it to display traditional
-  contextual menus.</p>
-</li>
-<li>
-<p>If you don't support multi-selection within a list, long press should do nothing.</p>
-</li>
-<li>
-<p>Plan the actions you want to display inside of a CAB in the same way you would plan the actions
-  inside your app's action bar.</p>
-</li>
-</ul>
diff --git a/docs/html/design/patterns/settings.jd b/docs/html/design/patterns/settings.jd
deleted file mode 100644
index 9ba837a..0000000
--- a/docs/html/design/patterns/settings.jd
+++ /dev/null
@@ -1,708 +0,0 @@
-page.title=Settings
-page.tags=preferences,sharedpreferences
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/patterns/settings.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Settings<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}guide/topics/ui/settings.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Settings</p>
-  </div>
-</a>
-
-
-<p itemprop="description">Settings is a place in your app where users indicate their preferences for how your app should
-behave. This benefits users because:</p>
-
-<ul>
-<li>You don't need to interrupt them with the same questions over and over when certain situations
-arise. The settings predetermine what will always happen in those situations (see design
-principle: <a href="{@docRoot}design/get-started/principles.html#decide-for-me">Decide for me but
-let me have the final say</a>).</li>
-<li>You help them feel at home and in control (see design principle:
-<a href="{@docRoot}design/get-started/principles.html#make-it-mine">Let me make it mine</a>).</li>
-</ul>
-
-<h2 id="flow-structure">Flow and Structure</h2>
-
-<h4 id="settings-access">Provide access to Settings in the action overflow</h4>
-
-<p>Settings is given low prominence in the UI because it's not frequently needed. Even if there's
-room in the <a href="{@docRoot}design/patterns/actionbar.html">action bar</a>, never make Settings
-an action button. Always keep it in the action overflow and label it "Settings". Place it below
-all other items except "Help".</p>
-
-<img src="{@docRoot}design/media/settings_overflow.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4 id="what-to-make-a-setting">Avoid the temptation to make everything a setting</h4>
-
-<p>Because Settings is a few navigational steps away, no matter how many items you have, they'll
-never clutter up the core part of your UI. This may seem like good news, but it also poses a
-challenge.</p>
-
-<p>Settings can be a tempting place to keep a lot of stuff&mdash;like a hall closet where things
-get stashed when you tidy up before company comes over. It's not a place where you spend lots of
-time, so it's easy to rationalize and ignore its cluttered condition. But when users visit
-Settings&mdash;however infrequently&mdash;they'll have the same expectations for the experience as
-they do everywhere else in your app. More settings means more choices to make, and too many are
-overwhelming.</p>
-
-<p>So don't punt on the difficult product decisions and debates that can bring on the urge to
-"just make it a setting". For each control you're considering adding to Settings, make sure it
-meets the bar:</p>
-
-<img src="{@docRoot}design/media/settings_flowchart.png">
-
-<div class="vspace size-3">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-5 with-callouts">
-
-<h4 id="group-settings">If you still have lots of settings, group related settings together</h4>
-
-<p>The number of items an average human can hold in short-term memory is 7&plusmn;2. If you
-present a list of 10 or more settings (even after applying the criteria above), users will have
-more difficulty scanning, comprehending, and processing them.</p>
-
-<p>You can remedy this by dividing some or all of the settings into groups, effectively turning
-one long list into multiple shorter lists. A group of related settings can be presented in one of
-two ways:</p>
-
-<ol>
-<li><h4>Under a section divider</h4></li>
-<li><h4>In a separate subscreen</h4></li>
-</ol>
-
-<p>You can use one or both these grouping techniques to organize your app's settings.</p>
-
-<p>For example, in the main screen of the Android Settings app, each item in the list navigates
-to a subscreen of related settings. In addition, the items themselves are grouped under section
-dividers.</p>
-
-  </div>
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/settings_grouping.png">
-
-  </div>
-</div>
-
-<p>Grouping settings is not an exact science, but here's some advice for how to approach it, based
-on the total number of settings in your app.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-2">
-
-<h4>7 or fewer</h4>
-
-  </div>
-  <div class="col-11">
-
-<p>Don't group them at all. It won't benefit users and will seem like overkill.</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-2">
-
-<h4>8 to 10</h4>
-
-  </div>
-  <div class="col-11">
-
-<p>Try grouping related settings under 1 or 2 section dividers. If you have any "singletons"
-(settings that don't relate to any other settings and can't be grouped under your section
-dividers), treat them as follows:</p>
-
-<ul>
-<li>If they include some of your most important settings, list them at the top without a section
-divider.</li>
-<li>Otherwise, list them at the bottom with a section divider called "OTHER", in order of
-importance.</li>
-</ul>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-2">
-
-<h4>11 to 15</h4>
-
-  </div>
-  <div class="col-11">
-
-<p>Same advice as above, but try 2 to 4 section dividers.</p>
-
-<p>Also, try the following to reduce the list:</p>
-
-<ul>
-<li>If 2 or more of the settings are mainly for power users, move them out of your main Settings
-screen and into an "Advanced" subscreen. Place an item in the action overflow called "Advanced" to
-navigate to it.</li>
-<li>Look for "doubles": two settings that relate to one another, but not to any other settings.
-Try to combine them into one setting, using the design patterns described later in this section.
-For example, you might be able to redesign two related checkbox settings into one multiple choice
-setting.</li>
-</ul>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-2">
-
-<h4>16 or more</h4>
-
-  </div>
-  <div class="col-11">
-
-<p>If you have any instances of 4 or more related settings, group them under a subscreen. Then use
-the advice suggested above for the reduced list size.</p>
-
-  </div>
-</div>
-
-
-<h2 id="patterns">Design Patterns</h2>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Checkbox</h4>
-<p>Use this pattern for a setting that is either selected or not selected.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_checkbox.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Multiple choice</h4>
-<p>Use this pattern for a setting that needs to present a discrete set of options, from which the
-user can choose only one.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_multiple_choice.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Slider</h4>
-<p>Use this pattern for a setting where the range of values are not discrete and fall along a
-continuum.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_slider.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Date/time</h4>
-<p>Use this pattern for a setting that needs to collect a date and/or time from the user.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_date_time.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Subscreen navigation</h4>
-<p>Use this pattern for navigating to a subscreen or sequence of subscreens that guide the user
-through a more complex setup process.</p>
-<ul>
-<li>If navigating to a single subscreen, use the same title in both the subscreen and the label
-navigating to it.</li>
-<li>If navigating to a sequence of subscreens (as in this example), use a title that describes the
-first step in the sequence.</li>
-</ul>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_subscreen_navigation.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>List subscreen</h4>
-<p>Use this pattern for a setting or category of settings that contains a list of equivalent items.
-</p>
-<p>The label provides the name of the item, and secondary text may be used for status. (In this
-example, status is reinforced with an icon to the right of the label.) Any actions associated with
-the list appear in the action bar rather than the list itself.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_list_subscreen.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Master on/off switch</h4>
-<p>Use this pattern for a category of settings that need a mechanism for turning on or off as a
-whole.</p>
-<p>An on/off switch is placed as the first item in the action bar of a subscreen. When the switch
-is turned off, the items in the list disappear, replaced by text that describes why the list is
-empty. If any actions require the switch to be on, they become disabled.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_master_on_off.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<p>You can also echo the master on/off switch in the menu item that leads to the subscreen.
-However, you should only do this in cases where users rarely need to access the subscreen once
-it's initially set up and more often just want to toggle the switch.</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_master_on_off_2.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Individual on/off switch</h4>
-<p>Use this pattern for an individual setting that requires a more elaborate description than can
-be provided in checkbox form.</p>
-<p>The on/off switch only appears in the subscreen so that users aren't able to toggle it without
-also being exposed to the descriptive text. Secondary text appears below the setting label to
-reflect the current selection.</p>
-<p>In this example, Android Beam is on by default. Since users might not know what this setting
-does, we made the status more descriptive than just "On".</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_individual_on_off.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Dependency</h4>
-<p>Use this pattern for a setting that changes availability based on the value of another setting.
-</p>
-<p>The disabled setting appears below its dependency, without any indentation. If the setting
-includes a status line, it says "Unavailable", and if the reason isn't obvious, a brief
-explanation is included in the status.</p>
-<p>If a given setting is a dependency to 3 or more settings, consider using a subscreen with a
-master on/off switch so that your main settings screen isn't cluttered by lots of disabled items.
-</p>
-
-  </div>
-  <div class="col-10">
-
-<img src="{@docRoot}design/media/settings_dependency.png">
-
-  </div>
-</div>
-
-<h2 id="defaults">Defaults</h2>
-
-<p>Take great care in choosing default values for each of your settings. Because settings
-determine app behavior, your choices will contribute to users' first impressions of your app. Even
-though users can change settings, they'll expect the initial states to be sensible. The following
-questions (when applicable) may help inform your decisions:</p>
-
-<ul>
-<li>Which choice would most users be likely to choose on their own if there were no default?</li>
-<li>Which choice is the most neutral or middle-of-the-road?</li>
-<li>Which choice is the least risky, controversial, or over-the-top?</li>
-<li>Which choice uses the least amount of battery or mobile data?</li>
-<li>Which choice best supports the design principle
-<a href="{@docRoot}design/get-started/principles.html#never-lose-my-stuff">Never lose my stuff</a>?</li>
-<li>Which choice best supports the design principle
-<a href="{@docRoot}design/get-started/principles.html#interrupt-only-if-important">Only interrupt
-me if it's important</a>?
-</li>
-</ul>
-
-<h2 id="writing">Writing Guidelines</h2>
-
-<h4>Label clearly and concisely</h4>
-
-<p>Writing a good label for a setting can be challenging because space is very limited. You only
-get one line, and it's incredibly short on the smallest of devices. Follow these guidelines to
-make your labels brief, meaningful, and scannable:</p>
-
-<ul>
-<li>Write each label in sentence case (i.e. only the first word and proper nouns are capitalized).
-</li>
-<li>Don't start a label with an instructional verb like "Set", "Change", "Edit", "Modify",
-"Manage", "Use", "Select", or "Choose". Users already understand that they can do these things to
-settings.</li>
-<li>Likewise, don't end a label with a word like "setting" or "settings". It's already implied.
-</li>
-<li>If the setting is part of a grouping, don't repeat the word(s) used in the section divider or
-subscreen title.</li>
-<li>Avoid starting a label with a negative word like "Don't" or "Never". For example, "Don't
-allow" could be rephrased to "Block".</li>
-<li>Steer clear of technical jargon as much as possible, unless it's a term widely understood by
-your target users. Use common verbs and nouns to convey the setting's purpose rather than its
-underlying technology.</li>
-<li>Don't refer to the user. For example, for a setting allowing the user to turn notifications on
-or off, label it "Notifications" instead of "Notify me".</li>
-</ul>
-
-<p>Once you've decided on labels for your settings, be sure to preview them on an
-<a href="{@docRoot}design/style/metrics-grids.html">LDPI handset</a> in portrait to make sure
-they'll fit everywhere.</p>
-
-<h4>Secondary text below is for status, not description&hellip;</h4>
-
-<p>Before Ice Cream Sandwich, we often displayed secondary text below a label to further describe
-it or provide instructions. Starting in Ice Cream Sandwich, we're using secondary text for status.
-</p>
-
-<div class="cols">
-  <div class="col-4">
-
-    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
-
-    <table class="ui-table bad emulate-content-left-padding">
-    <thead>
-      <tr>
-        <th class="label">
-        Screen timeout
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        Adjust the delay before the screen automatically turns off
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-4">
-
-    <div class="do-dont-label good">After</div>
-
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th class="label">
-        Sleep
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        After 10 minutes of inactivity
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-</div>
-
-<p>Status in secondary text has the following benefits:</p>
-<ul>
-<li>Users can see at a glance what the current value of a setting is without having to navigate
-any further.</li>
-<li>It applies the design principle
-<a href="{@docRoot}design/get-started/principles.html#keep-it-brief">Keep it brief</a>, which
-users greatly appreciate.</li>
-</ul>
-
-<h4>&hellip;unless it's a checkbox setting</h4>
-<p>There's one important exception to the using secondary text for status: checkbox settings.
-Here, use secondary text for description, not status. Status below a checkbox is unnecessary
-because the checkbox already indicates it. The reason why it's appropriate to have a description
-below a checkbox setting is because&mdash;unlike other controls&mdash;it doesn't display a dialog
-or navigate to another screen where additional information can be provided.</p>
-
-<p>That said, if a checkbox setting's label is clear enough on its own, there's no need to also
-provide a description. Only include one if necessary.</p>
-
-<p>Follow these guidelines to write checkbox setting descriptions:</p>
-<ul>
-<li>Keep it to one sentence and don't use ending punctuation.</li>
-<li>Convey what happens when the setting is checked, phrased in the form of a command. Example:
-"Allow data exchange", not "Allows data exchange".</li>
-<li>Avoid repetition by choosing words that don't already appear in the label.</li>
-<li>Don't refer to the user unless it's necessary for understanding the setting.</li>
-<li>If you must refer to the user, do so in the second person ("you") rather than the first person
-("I"). Android speaks to users, not on behalf of them.</li>
-</ul>
-
-<h4>Writing examples</h4>
-
-<p>The following are examples of changes we made to labels and secondary text in the Settings app
-in Ice Cream Sandwich.</p>
-
-<div class="cols">
-  <div class="col-4">
-
-    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
-
-    <table class="ui-table bad emulate-content-left-padding">
-    <thead>
-      <tr>
-        <th class="label">
-        Use tactile feedback
-        </th>
-      </tr>
-    </thead>
-    </table>
-
-  </div>
-  <div class="col-4">
-
-    <div class="do-dont-label good">After</div>
-
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th class="label">
-        Vibrate on touch
-        </th>
-      </tr>
-    </thead>
-    </table>
-
-  </div>
-  <div class="col-5">
-
-<p>In this checkbox setting, we eliminated the throwaway word "Use" and rephrased the label to be
-more direct and understandable.</p>
-
-  </div>
-
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
-
-    <table class="ui-table bad emulate-content-left-padding">
-    <thead>
-      <tr>
-        <th class="label">
-        Screen timeout
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        Adjust the delay before the screen automatically turns off
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-4">
-
-    <div class="do-dont-label good">After</div>
-
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th class="label">
-        Sleep
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        After 10 minutes of inactivity
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-5">
-
-<p>In this multiple choice setting, we changed the label to a friendlier term and also replaced
-the description with status. We put some descriptive words around the selected value, "10
-minutes", because on its own, the meaning could be misinterpreted as "sleep for 10 minutes".</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
-
-    <table class="ui-table bad emulate-content-left-padding">
-    <thead>
-      <tr>
-        <th class="label">
-        Change screen lock
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        Change or disable pattern, PIN, or password security
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-4">
-
-    <div class="do-dont-label good">After</div>
-
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th class="label">
-        Screen lock
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        Pattern
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-5">
-
-<p>This setting navigates to a a sequence of subscreens that allow users to choose a type of
-screen lock and then set it up. We eliminated the throwaway word "Change" in the label, and
-replaced the description with the current type of screen lock set up by the user. If the user
-hasn't set up a screen lock, the secondary text says "None".</p>
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
-
-    <table class="ui-table bad emulate-content-left-padding">
-    <thead>
-      <tr>
-        <th class="label">
-        NFC
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        Use Near Field Communication to read and exchange tags
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-4">
-
-    <div class="do-dont-label good">After</div>
-
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th class="label">
-        NFC
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td class="secondary-text">
-        Allow data exchange when the phone touches another device
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-5">
-
-<p>In this checkbox setting&mdash;although it's technical jargon&mdash;we kept the "NFC" label
-because: (1) we couldn't find a clear, concise alternative, and (2) user familiarity with the
-acronym is expected to increase dramatically in the next couple of years.</p>
-<p>We did, however, rewrite the description. It's far less technical than before and does a better
-job of conveying how and why you'd use NFC. We didn't include what the acronym stands for because
-it doesn't mean anything to most users and would have taken up a lot of space.</p>
-
-  </div>
-</div>
-
-
-
-<h2 id="checklist">Checklist</h2>
-<ul>
-<li><p>Make sure each item in Settings meets the criteria for belonging there.</p></li>
-<li><p>If you have more than 7 items, explore ways to group related settings.</p></li>
-<li><p>Use design patterns wherever applicable so users don't face a learning curve.</p></li>
-<li><p>Choose defaults that are safe, neutral, and fit the majority of users.</p></li>
-<li><p>Give each setting a clear, concise label and use secondary text appropriately.</p></li>
-</ul>
diff --git a/docs/html/design/style/branding.jd b/docs/html/design/style/branding.jd
deleted file mode 100644
index 5995d03..0000000
--- a/docs/html/design/style/branding.jd
+++ /dev/null
@@ -1,128 +0,0 @@
-page.title=Your Branding
-page.tags=branding,logo
-@jd:body
-
-<p>Following Android design patterns doesn't mean that your app has to look the same as
-everyone else's. In Android, your app can shine as an extension of your brand. </p>
-
-<h2 id="color">Color</h2>
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/style/color.html#color-ui-color-application">
-  <div>
-    <h3>Material Design</h3>
-    <p>UI Color Application<p>
-  </div>
-</a>
-
-<p>Use your brand color for accent by overriding the Android framework's default blue in UI elements like checkboxes, progress bars, radio buttons, sliders, tabs, and scroll indicators.</p>
-
-<p>Look for opportunities to use high-contrast color for emphasis, for example, as the background color of the action bar or a primary button. But don't go overboard: not all actions are equal, so use it only for the one or two most important things.</p>
-<p>When customizing colors, <a href="{@docRoot}design/style/touch-feedback.html">touch feedback</a>
-  should be subtle &mdash; just slightly lighter or darker than the untouched color.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-6">
-    <img src="{@docRoot}design/media/branding_wallet.png" style="width:94%">
-    <div class="figure-caption">
-      The four colors of the Google Wallet logo provide a playful accent to the four dots
-      that appear as the user enters a PIN.
-    </div>
-  </div>
-  <div class="col-6">
-    <img src="{@docRoot}design/media/branding_googlemusic.png" style="width:94%">
-    <div class="figure-caption">
-      The Google Play Music app has an orange theme color, which is used for emphasis
-      in the action bar and for accent in the selected tab, scroll indicator, and
-      hyperlinks.
-    </div>
-  </div>
-</div>
-
-<h2 id="logo">Logo</h2>
-
-<p>Your app's <a href="{@docRoot}design/style/iconography.html#launcher">launcher icon</a> is
-  a key place to incorporate your logo, because it's what
-  users will look for and touch to begin using your app. You can carry the launcher
-  icon through to all the screens in your app by showing it in the
-  <a href="{@docRoot}design/patterns/actionbar.html">action bar</a> along
-  with the name of the app.</p>
-
-<p>Another approach to consider is to have your logo take the place of the launcher icon
-and app name in the action bar.</p>
-
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-6" style="padding-top:24px;">
-        <img src="{@docRoot}design/media/branding_launcher_icon.png" style="width:60px;float:left;padding-right:1em;">
-    <div class="figure-caption" style="width:290px;margin-left:20px;">
-    Google+ reinforces its brand by carrying its launcher icon through to the action bar.
-    </div>
-        <img src="{@docRoot}design/media/branding_logo_icon_action_bar.png" style="width:320px;float:left;padding-right:1em;">
-  </div>
-  <div class="col-6">
-    <img src="{@docRoot}design/media/yourbranding_app.png" style="width:320px;">
-    <div class="figure-caption" style="width:320px;">
-      Example of a the logo in the action bar. This works well in cases where the brand's logo matches the name of the app.
-    </div>
-  </div>
-</div>
-
-<h2 id="logo">Icons</h2>
-
-<a class="notice-designers-material" href="http://www.google.com/design/spec/style/icons.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Icons<p>
-  </div>
-</a>
-
-<p>If you have icons that you're already using for your app on other platforms
-and they have a distinctive look intended to fit your brand, use them on your
-Android app as well. <strong>If you take this approach, make sure your brand styling is
-applied to every single icon in your app.</strong></p>
-
-
-<div class="cols">
-  <div class="col-6">
-    <p>One exception: For any icon in your existing set where the symbol is different from
-    Android's, use Android's symbol but give it your brand's styling. That way, users will
-    understand what the purpose of the icon is based on what they've learned in other
-    Android apps (Design principle:
-    <a href="{@docRoot}design/get-started/principles.html#give-me-tricks">Give me tricks that
-    work everywhere</a>). But the icon will still look like it belongs with all of
-    your other icons as a part of your brand.</p>
-
-  </div>
-
-  <div class="col-6">
-    <img src="{@docRoot}design/media/yourbranding_in-app-icons.png" style="width:300px;margin:12px 48px 0 16px;">
-    </div>
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-6">
-    <p><strong>Example</strong>:<br />
-    </p>
-    <p>The brand's normal icon for sharing on other platforms is a right arrow.
-  </div>
-
-  <div class="col-6 lasyout-with-list-item-margins">
-
-    <div style="margin-bottom:1em;">
-      <span class="do-dont-label bad" style="margin-left:12px">Don't</span>
-      <span style="margin-left: 64px;"  class="do-dont-label good"><strong>Do</strong></span>
-    </div>
-      <img src="{@docRoot}design/media/yourbranding_sharing.png" style="width:180px;">
-  </div>
-</div>
-
-<p>What if you don't already have your own icons &mdash; for example, if you're creating a
-brand new app only for Android? In this case, use Android's standard icons and rely
-more on color and logo for branding. Get the Action Bar Icon Pack, available for free
-in <a href="{@docRoot}design/downloads/index.html">Downloads</a>.</p>
diff --git a/docs/html/design/style/color.jd b/docs/html/design/style/color.jd
deleted file mode 100644
index 4c5f5ab..0000000
--- a/docs/html/design/style/color.jd
+++ /dev/null
@@ -1,141 +0,0 @@
-page.title=Color
-@jd:body
-
-<style>
-  .color-row {
-    width: 760px;
-    margin:0;
-
-    display: -webkit-box;
-    display:    -moz-box;
-    display:         box;
-
-    -webkit-box-orient: horizontal;
-       -moz-box-orient: horizontal;
-            box-orient: horizontal;
-
-    cursor: pointer;
-
-    -webkit-user-select: none;
-            user-select: none;
-    /* nested user-select in FF is broken as of Jan 2012, don't use it */
-  }
-
-  .color-row-container {
-    line-height: 0; /* to remove more top space in FF for -moz-box elements */
-  }
-
-  .color-row-container + .color-row-container {
-    margin-top: -10px !important;
-  }
-
-  .color-row li {
-    margin-left: 0 !important;
-    position: relative;
-    list-style-type: none;
-    height: 80px;
-    display: block;
-
-    -webkit-box-flex: 1;
-       -moz-box-flex: 1;
-            box-flex: 1;
-  }
-
-  .color-row li:before {
-    display: none;
-  }
-
-  .color-row li.thin {
-    height: 40px;
-  }
-
-  .color-row li span {
-    display: none;
-    position: absolute;
-    top: -30px;
-    left: 50%;
-    margin-left: -2.5em;
-    width: 5em;
-    background-color: #fff;
-    padding: 10px;
-    font-weight: 600;
-    line-height: 20px;
-    text-align: center;
-    box-shadow: 0 5px 5px rgba(0,0,0,0.1);
-    cursor: text;
-
-    -webkit-user-select: text;
-            user-select: text;
-    /* nested user-select in FF is broken as of Jan 2012, don't use it */
-  }
-
-  .color-row li:hover span {
-    display: block;
-  }
-
-  /* triangle callout */
-  .color-row li span:after {
-    content: '';
-    display: block;
-    position: absolute;
-    left: 50%;
-    bottom: -16px;
-    border: 8px solid transparent;
-    border-top-color: #fff;
-    width: 0;
-    height: 0;
-    margin-left: -8px;
-  }
-</style>
-
-<a class="notice-designers-material" href="http://www.google.com/design/spec/style/color.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Color<p>
-  </div>
-</a>
-
-<p>Use color primarily for emphasis. Choose colors that fit with your brand and provide good contrast
-between visual components. Note that red and green may be indistinguishable to color-blind users.</p>
-
-    <div class="color-row-container">
-      <ul class="color-row">
-        <li><span>#33b5e5</span></li>
-        <li><span>#aa66cc</span></li>
-        <li><span>#99cc00</span></li>
-        <li><span>#ffbb33</span></li>
-        <li><span>#ff4444</span></li>
-      </ul>
-    </div>
-
-    <div class="color-row-container">
-      <ul class="color-row">
-        <li class="thin"><span>#0099cc</span></li>
-        <li class="thin"><span>#9933cc</span></li>
-        <li class="thin"><span>#669900</span></li>
-        <li class="thin"><span>#ff8800</span></li>
-        <li class="thin"><span>#cc0000</span></li>
-      </ul>
-    </div>
-
-<h2 id="palette">Palette</h2>
-
-<p>Blue is the standard accent color in Android's color palette. Each color has a corresponding darker
-shade that can be used as a complement when needed.</p>
-<p><a onClick="ga('send', 'event', 'Design', 'Download', 'Color Swatches (@color page)');"
-      href="{@docRoot}downloads/design/Android_Design_Color_Swatches_20120229.zip">Download the swatches</a></p>
-
-<img src="{@docRoot}design/media/color_spectrum.png">
-
-<script>
-  $(document).ready(function() {
-    $('.color-row li').each(function() {
-      var color = $(this).text();
-      $(this).css('background-color', color);
-      $(this).find('span')
-          .css('color', color)
-          .text(color.toUpperCase());
-    });
-
-  });
-</script>
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
deleted file mode 100644
index 8b6f3ab..0000000
--- a/docs/html/design/style/iconography.jd
+++ /dev/null
@@ -1,601 +0,0 @@
-page.title=Iconography
-page.tags="icons"
-meta.tags="icons, googleplay, listing, branding"
-page.titleFriendly=Guidelines for creating your app's icons
-@jd:body
-
-<img src="{@docRoot}design/media/iconography_overview.png">
-
-
-<p>An icon is a graphic that takes up a small portion of screen real estate and provides a quick,
-intuitive representation of an action, a status, or an app.</p>
-
-<p>When you design icons for your app, it's important to keep in mind that your
-app may be installed on a variety of devices that offer a range of
-pixel densities, as mentioned in
-<a href="{@docRoot}design/style/devices-displays.html">Devices
-and Displays</a>. But you can make your icons look great on all devices
-by providing each icon in multiple sizes. When your app runs, Android checks the characteristics of
-the device screen and loads the appropriate density-specific assets for your app. </p>
-
-<p>Because you will deliver each icon in multiple sizes to support different densities,
-the design guidelines below
-refer to the icon dimensions in <acronym title="density-independent pixels">dp</acronym>
-units, which are based on the pixel dimensions of a medium-density (MDPI) screen.</p>
-
-<img src="{@docRoot}design/media/devices_displays_density@2x.png" alt="" height="160" />
-
-<p>So, to create an icon for different densities, you should follow the <strong>2:3:4:6:8
-scaling ratio</strong> between the five primary densities (medium, high, x-high, xx-high, and
-xxx-high respectively). For example, consider that the size for a launcher icon is specified to be
-48x48 dp. This means the baseline (MDPI) asset is 48x48 px, and the
-high-density(HDPI) asset should be 1.5x the baseline at 72x72 px, and the x-high
-density (XHDPI) asset should be 2x the baseline at 96x96 px, and so on.</p>
-
-<p class="note"><strong>Note:</strong> Android also supports low-density (LDPI) screens,
-but you normally don't need to create custom assets at this size because Android
-effectively down-scales your HDPI assets by 1/2 to match the expected size.</p>
-
-
-
-
-<h2 id="launcher">Launcher</h2>
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/style/icons.html#icons-product-icons">
-  <div>
-    <h3>Material Design</h3>
-    <p>Product Icons<p>
-  </div>
-</a>
-
-<p>The launcher icon is the visual representation of your app on the Home or All Apps screen. Since the
-user can change the Home screen's wallpaper, make sure that your launcher icon is clearly visible on
-any type of background.</p>
-
-<div class="cols">
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_launcher_size.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_launcher_focal.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_launcher_style.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Launcher icons on a mobile device must be <strong>48x48 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-      <li class="no-bullet with-icon web">
-        <p>Launcher icons for display on Google Play must be <strong>512x512 pixels</strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-    <h4>Proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>48x48 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-<h4>Style</h4>
-<p>Use a distinct silhouette. Three-dimensional, front view, with a slight perspective as if viewed
-from above, so that users perceive some depth.</p>
-
-  </div>
-</div>
-
-
-<div class="cols">
-  <div class="col-4">
-    &nbsp;
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/iconography_launcher_example.png">
-
-  </div>
-  <!-- 2 free columns -->
-</div>
-
-<div class="cols">
-  <div class="col-12">
-
-    <img src="{@docRoot}design/media/iconography_launcher_example2.png">
-
-    <div class="vspace size-2">&nbsp;</div>
-
-  </div>
-  <!-- 1 free columns -->
-</div>
-
-
-<h2 id="action-bar">Action Bar</h2>
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/style/icons.html#icons-system-icons">
-  <div>
-    <h3>Material Design</h3>
-    <p>System Icons<p>
-  </div>
-</a>
-
-<p>
-
-Action bar icons are graphic buttons that represent the most important actions people can take
-within your app. Each one should employ a simple metaphor representing a single concept that most
-people can grasp at a glance.
-
-</p>
-<p>
-
-Pre-defined glyphs should be used for certain common actions such as "refresh" and "share." The
-download link below provides a package with icons that are scaled for various screen densities and
-are suitable for use with the Holo Light and Holo Dark themes. The package also includes unstyled
-icons that you can modify to match your theme, in addition to Adobe&reg; Illustrator&reg; source
-files for further customization.
-
-</p>
-<p>
-<a onClick="ga('send', 'event', 'Design', 'Download', 'Action Bar Icons (@iconography page)');"
-   href="{@docRoot}downloads/design/Android_Design_Icons_20131106.zip">Download the Action Bar Icon Pack</a>
-</p>
-
-<div class="cols">
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_actionbar_size.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_actionbar_focal.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_actionbar_style.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Action bar icons for phones should be <strong>32x32 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-    <h4>Focal area &amp; proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>32x32 dp</strong></p>
-        <p>Optical square, <strong>24x24 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-<h4>Style</h4>
-<p>Pictographic, flat, not too detailed, with smooth curves or sharp shapes. If the graphic is thin,
-rotate it 45&deg; left or right to fill the focal space. The thickness of the strokes and negative
-spaces should be a minimum of 2 dp.</p>
-
-  </div>
-</div>
-
-
-<div class="cols">
-  <div class="col-3">
-
-<h4>Colors</h4>
-<p>Colors: <strong>#333333</strong><br />
-Enabled: <strong>60%</strong> opacity<br />
-Disabled: <strong>30%</strong> opacity</p>
-<div class="vspace size-1">&nbsp;</div>
-
-<p>Colors: <strong>#FFFFFF</strong><br />
-Enabled: <strong>80%</strong> opacity<br />
-Disabled: <strong>30%</strong> opacity</p>
-
-  </div>
-  <div class="col-9">
-
-    <img src="{@docRoot}design/media/iconography_actionbar_colors.png">
-
-  </div>
-</div>
-
-
-<h2 id="small-contextual">Small / Contextual Icons</h2>
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/style/icons.html#icons-system-icons">
-  <div>
-    <h3>Material Design</h3>
-    <p>System Icons<p>
-  </div>
-</a>
-
-<p>Within the body of your app, use small icons to surface actions and/or provide status for specific
-items. For example, in the Gmail app, each message has a star icon that marks the message as
-important.</p>
-
-
-<div class="cols">
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_small_size.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_small_focal.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_small_style.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Small icons should be <strong>16x16 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-    <h4>Focal area &amp; proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>16x16 dp</strong></p>
-        <p>Optical square, <strong>12x12 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-<h4>Style</h4>
-<p>Neutral, flat, and simple. Filled shapes are easier to see than thin strokes. Use a single visual
-metaphor so that a user can easily recognize and understand its purpose.</p>
-
-  </div>
-</div>
-
-
-<div class="cols">
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_small_colors.png">
-
-    <div class="vspace size-2">&nbsp;</div>
-
-<h4>Colors</h4>
-<p>Use non-neutral colors sparingly and with purpose. For example, Gmail uses yellow in the star icon
-to indicate a bookmarked message. If an icon is actionable, choose a color that contrasts well with
-the background.</p>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/iconography_small_example.png">
-
-  </div>
-  <!-- 2 free columns -->
-</div>
-
-
-<h2 id="notification">Notification Icons</h2>
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/style/icons.html#icons-system-icons">
-  <div>
-    <h3>Material Design</h3>
-    <p>System Icons<p>
-  </div>
-</a>
-
-
-<p>If your app generates notifications, provide an icon that the system can display in the status bar
-whenever a new notification is available.</p>
-
-
-<div class="cols">
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_notification_size.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_notification_focal.png">
-
-  </div>
-  <div class="col-4">
-
-    <img src="{@docRoot}design/media/iconography_notification_style.png">
-
-  </div>
-</div>
-
-<div class="cols">
-  <div class="col-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Notification icons must be <strong>24x24 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-    <h4>Focal area &amp; proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>24x24 dp</strong></p>
-        <p>Optical square, <strong>22x22 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="col-4">
-
-<h4>Style</h4>
-<p>Keep the style flat and simple, using the same single, visual metaphor as your launcher icon.</p>
-
-  </div>
-</div>
-
-
-<div class="cols">
-  <div class="col-4">
-
-<h4>Colors</h4>
-<p>Notification icons must be entirely white. Also, the system may scale down and/or darken the icons.</p>
-
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/iconography_notification_example.png">
-
-  </div>
-  <!-- 2 free columns -->
-</div>
-
-
-
-
-
-
-
-
-
-
-<h2 id="DesignTips">Design Tips</h2>
-
-<p>Here are some tips you might find useful as you create icons or other
-drawable assets for your application. These tips assume you are using
-Adobe&reg; Photoshop&reg; or a similar raster and vector image-editing program.</p>
-
-
-
-
-<h3>Use vector shapes where possible</h3>
-
-<p>Many image-editing programs such as Adobe&reg; Photoshop&reg; allow you to use a
-combination of vector shapes and raster layers and effects. When possible,
-use vector shapes so that if the need arises, assets can be scaled up without
-loss of detail and edge crispness.</p>
-
-<p>Using vectors also makes it easy to align edges and corners to pixel
-boundaries at smaller resolutions.</li>
-
-
-
-<h3>Start with large artboards</h3>
-
-<p>Because you will need to create assets for different screen densities,
-it is best to start your icon
-designs on large artboards with dimensions that are multiples of the target icon
-sizes. For example, launcher icons are 48, 72, 96, or 144 pixels wide,
-depending on screen density (mdpi, hdpi, xhdpi, and xxhdpi, respectively). If you
-initially draw launcher icons on an 864x864 artboard, it will be easier and
-cleaner to adjust the icons when you scale the artboard down to the target
-sizes for final asset creation.</p>
-
-
-
-<h3>When scaling, redraw bitmap layers as needed</h3>
-
-<p>If you scaled an image up from a bitmap layer, rather than from a vector
-layer, those layers will need to be redrawn manually to appear crisp at higher
-densities. For example if a 60x60 circle was painted as a bitmap for
-mdpi it will need to be repainted as a 90x90 circle for hdpi.</p>
-
-
-
-<h3>Use common naming conventions for icon assets</h3>
-
-<p>Try to name files so that related assets will group together inside a
-directory when they are sorted alphabetically. In particular, it helps to use a
-common prefix for each icon type. For example:</p>
-
-<table>
-<tr>
-<th>Asset Type</th>
-<th>Prefix</th>
-<th>Example</th>
-</tr>
-<tr>
-<td>Icons</td>
-<td><code>ic_</code></td>
-<td><code>ic_star.png</code></td>
-</tr>
-<tr>
-<td>Launcher icons</td>
-<td><code>ic_launcher</code></td>
-<td><code>ic_launcher_calendar.png</code></td>
-</tr>
-<tr>
-<td>Menu icons and Action Bar icons</td>
-<td><code>ic_menu</code></td>
-<td><code>ic_menu_archive.png</code></td>
-</tr>
-<tr>
-<td>Status bar icons</td>
-<td><code>ic_stat_notify</code></td>
-<td><code>ic_stat_notify_msg.png</code></td>
-</tr>
-<tr>
-<td>Tab icons</td>
-<td><code>ic_tab</code></td>
-<td><code>ic_tab_recent.png</code></td>
-</tr>
-<tr>
-<td>Dialog icons</td>
-<td><code>ic_dialog</code></td>
-<td><code>ic_dialog_info.png</code></td>
-</tr>
-</table>
-
-<p>Note that you are not required to use a shared prefix of any
-type&mdash;doing so is for your convenience only.</p>
-
-
-<h3>Set up a working space that organizes files by density</h3>
-
-<p>Supporting multiple screen densities means you must create multiple versions
-of the same icon. To help keep the multiple copies of files safe and easier to
-find, we recommend creating a directory structure in your working space that
-organizes asset files based on the target density. For example:</p>
-
-<pre>
-art/...
-    mdpi/...
-        _pre_production/...
-            <em>working_file</em>.psd
-        <em>finished_asset</em>.png
-    hdpi/...
-        _pre_production/...
-            <em>working_file</em>.psd
-        <em>finished_asset</em>.png
-    xhdpi/...
-        _pre_production/...
-            <em>working_file</em>.psd
-        <em>finished_asset</em>.png
-    xxhdpi/...
-        _pre_production/...
-            <em>working_file</em>.psd
-        <em>finished_asset</em>.png
-</pre>
-
-<p>Because the structure in your working space is similar to that of the application, you
-can quickly determine which assets should be copied to each
-resources directory. Separating assets by density also helps you detect any
-variances in filenames across densities, which is important because
-corresponding assets for different densities must share the same filename.</p>
-
-<p>For comparison, here's the resources directory structure of a typical
-application: </p>
-
-<pre>res/...
-    drawable-ldpi/...
-        <em>finished_asset</em>.png
-    drawable-mdpi/...
-        <em>finished_asset</em>.png
-    drawable-hdpi/...
-        <em>finished_asset</em>.png
-    drawable-xhdpi/...
-        <em>finished_asset</em>.png
-    drawable-xxhdpi/...
-        <em>finished_asset</em>.png
-
-    mipmap-ldpi/...
-        <em>finished_launcher_asset</em>.png
-    mipmap-mdpi/...
-        <em>finished_launcher_asset</em>.png
-    mipmap-hdpi/...
-        <em>finished_launcher_asset</em>.png
-    mipmap-xhdpi/...
-        <em>finished_launcher_asset</em>.png
-    mipmap-xxhdpi/...
-        <em>finished_launcher_asset</em>.png
-    mipmap-xxxhdpi/...
-        <em>finished_launcher_asset</em>.png
-</pre>
-
-<p>For more information about how to save resources in the application project,
-see <a href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a>.
-</p>
-
-<p> For more information about using the mipmap folders, see
-<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
-
-<h3 id="xxxhdpi-launcher">Provide an xxx-high-density launcher icon</h3>
-
-<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density
-launcher icon image is already extra-extra-high density, the scaling process will make it appear
-less crisp. So you should provide a higher density launcher icon in the <code>mipmap-xxxhdpi
-</code> directory, which the system uses instead of scaling up a smaller version of the icon.</p>
-
-<p class="note"><strong>Note:</strong> The <code>mipmap-xxxhdpi</code> qualifier is necessary
-only to provide a launcher icon that can appear larger than usual on an xxhdpi device. It is best
-practice to place all your launcher icons in the <code>res/mipmap-[density]/</code> folders. This
-enables your app to display launcher icons that have a higher density than the device, without
-scaling up a lower density version of the icon. You do not need to provide xxxhdpi assets for all
-your app's images.</p>
-
-<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> for
-more information.</p>
-
-
-<h3>Remove unnecessary metadata from final assets</h3>
-
-<p>Although the Android SDK tools will automatically compress PNGs when packaging
-application resources into the application binary, a good practice is to remove
-unnecessary headers and metadata from your PNG assets. Tools such as <a
-href="http://optipng.sourceforge.net/">OptiPNG</a> or <a
-href="http://pmt.sourceforge.net/pngcrush/">Pngcrush</a> can ensure that this
-metadata is removed and that your image asset file sizes are optimized.</p>
-
-
diff --git a/docs/html/design/style/metrics-grids.jd b/docs/html/design/style/metrics-grids.jd
deleted file mode 100644
index 97915b8..0000000
--- a/docs/html/design/style/metrics-grids.jd
+++ /dev/null
@@ -1,90 +0,0 @@
-page.title=Metrics and Grids
-page.metaDescription=Optimize your app's UI by designing layouts based on density-independent grids.
-page.tags="layout","screens"
-meta.tags="multiple screens, layout, tablets"
-page.image=/design/media/metrics_closeup.png
-@jd:body
-
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/layout/metrics-keylines.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Metrics and Keylines<p>
-  </div>
-</a>
-
-
-<p>Devices vary not only in physical size, but also in screen density (<acronym title="Dots per
-inch">DPI</acronym>). To simplify the way you design for multiple screens, think of each device as
-falling into a particular size bucket and density bucket:</p>
-<ul>
- <li>The size buckets are <em>handset</em> (smaller than
-600<acronym title="Density-independent pixels: One dp is one pixel on a 160 dpi (mdpi)
-screen.">dp</acronym>) and <em>tablet</em> (larger than or equal 600dp).</li>
- <li>The density buckets are <acronym
-title="Low density (120 dpi)">LDPI</acronym>, <acronym title="Medium density (160
-dpi)">MDPI</acronym>, <acronym title="High density (240 dpi)">HDPI</acronym>, <acronym title
-="Extra-high density (320 dpi)">XHDPI</acronym>, <acronym title
-="Extra-extra!-high density (480 dpi)">XXHDPI</acronym>, and <acronym title
-="Extra-extra-extra!-high density (640 dpi)">XXXHDPI</acronym>.</li>
-</ul>
-
-<p>Optimize your application's UI by designing
-alternative layouts for some of the different size buckets, and provide alternative bitmap images
-for different density buckets.</p>
-
-<p>Because it's important that you design and implement your layouts for multiple densities,
-the guidelines below and throught the documentation
-refer to layout dimensions with <acronym title="Density-independent pixels: One dp is one pixel
-on a 160 dpi (mdpi) screen.">dp</acronym> measurements instead of pixels.</p>
-
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/metrics_diagram.png">
-
-  </div>
-  <div class="col-5">
-
-<h4>Space considerations</h4>
-<p>Devices vary in the amount of density-independent pixels (dp) they can display.</p>
-<p>To see more, visit the
-<a href="http://developer.android.com/resources/dashboard/screens.html" target="_blank">
-Screen Sizes and Densities Device Dashboard</a>.</p>
-
-  </div>
-</div>
-
-
-<h2 id="48dp-rhythm">48dp Rhythm</h2>
-
-<p>Touchable UI components are generally laid out along 48dp units.</p>
-
-<img src="{@docRoot}design/media/metrics_48.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4>Why 48dp?</h4>
-<p>On average, 48dp translate to a physical size of about 9mm (with some variability). This is
-comfortably in the range of recommended target sizes (7-10 mm) for touchscreen objects and users
-will be able to reliably and accurately target them with their fingers.</p>
-<p>If you design your elements to be at least 48dp high and wide you can guarantee that:</p>
-<ul>
-<li>your targets will never be smaller than the minimum recommended target size of 7mm regardless of
-  what screen they are displayed on.</li>
-<li>you strike a good compromise between overall information density on the one hand, and
-  targetability of UI elements on the other.</li>
-</ul>
-
-<img src="{@docRoot}design/media/metrics_closeup.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4>Mind the gaps</h4>
-<p>Spacing between each UI element is 8dp.</p>
-
-<h2 id="examples">Examples</h2>
-
-<img src="{@docRoot}design/media/metrics_forms.png">
diff --git a/docs/html/design/style/themes.jd b/docs/html/design/style/themes.jd
deleted file mode 100644
index 6c8169b..0000000
--- a/docs/html/design/style/themes.jd
+++ /dev/null
@@ -1,53 +0,0 @@
-page.title=Themes
-@jd:body
-
-<div class="cols">
-  <div class="col-5">
-
-    <img src="{@docRoot}design/media/themes_holo_light.png">
-    <div class="figure-caption">
-      Gmail in Holo Light.
-    </div>
-
-    <img src="{@docRoot}design/media/themes_holo_dark.png">
-    <div class="figure-caption">
-      Settings in Holo Dark.
-    </div>
-
-  </div>
-  <div class="col-7">
-
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/style/color.html#color-themes">
-  <div>
-    <h3>Material Design</h3>
-    <p>Color Themes<p>
-  </div>
-</a>
-
-
-<p>Themes are Android's mechanism for applying a consistent style to an app or activity.
-The style specifies the visual properties of the elements that make up your user interface,
-such as color, height, padding and font size. To promote greater cohesion between all apps
-on the platform, Android provides two system themes that you can choose from when building apps:</p>
-<ul>
-<li>Holo Light</li>
-<li>Holo Dark</li>
-</ul>
-<p>Applying these themes will go a long way in helping you to build apps that fit right into the
-general visual language of Android.</p>
-<p>Pick the system theme that best matches the needs and design aesthetics for your app. If your
-desire is to have a more distinct look for your app, using one of the system themes as a starting
-point for your customizations is a good idea. The system themes provide a solid foundation on top
-of which you can selectively implement your own visual stylings.</p>
-
-<div class="note develop">
-<p><strong>Developer Guide</strong></p>
-  <p>For information about how to apply themes such as Holo Light and Dark, and
-  how to build your own themes, see the
-  <a href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a> API guide.</p>
-</div>
-
-  </div>
-</div>
diff --git a/docs/html/design/style/touch-feedback.jd b/docs/html/design/style/touch-feedback.jd
deleted file mode 100644
index e1fac2f..0000000
--- a/docs/html/design/style/touch-feedback.jd
+++ /dev/null
@@ -1,95 +0,0 @@
-page.title=Touch Feedback
-page.tags=input,button
-@jd:body
-
-<div class="cols" style="margin-bottom: -100px">
-<div class="col-7">
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/animation/responsive-interaction.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Responsive Interaction<p>
-  </div>
-</a>
-
-
-<p>Use illumination and dimming to respond to touches, reinforce the resulting behaviors
-of gestures, and indicate what actions are enabled and disabled.</p>
-
-<p><strong>Be responsive to touches in a gentle way</strong>. Whenever a user touches an
-actionable area in your app, let them know the app is "listening" by providing a visual
-response. Make it subtle &mdash;just slightly lighter or darker than the untouched color. This
-provides two benefits:</p>
-
-<ul>
-<li><a href="{@docRoot}design/get-started/principles.html#sprinkle-encouragement">Sprinkles
-of encouragement</a> are more pleasant than jolts.</li>
-<li>Incorporating <a href="{@docRoot}design/style/branding.html">your branding</a> is much
-easier because the default touch feedback works with whatever hue you choose.</li>
-</ul>
-
-</div>
-
-<div class="col-6" style="float:right;">
-  <video  class="play-on-hover" width="268" height="442" autoplay style="border:1px solid #ddd;background-color:#f9f9f9;" poster="">
-    <source src="{@docRoot}design/media/touch_feedback.mp4" type="video/mp4">
-    <source src="{@docRoot}design/media/touch_feedback.webm" type="video/webm">
-    <source src="{@docRoot}design/media/touch_feedback.ogv" type="video/ogg">
-  </video>
-  <div class="figure-caption">
-    <div style="color:#a3a3a3;margin-left:130px;"><em>Click image to replay...</em></div>
-  </div>
-</div>
-
-<h4 style="clear:both;">States</h4>
-
-
-<div class="vspace size-1">&nbsp;</div>
-
-<img src="{@docRoot}design/media/touch_feedback_states.png">
-<div class="figure-caption">
-  Most of Android's UI elements have touch feedback built in, including
-  states that indicate whether touching the element will have any effect.
-</div>
-
-<div class="vspace size-3">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-6">
-
-    <h4>Communication</h4>
-<p>When your objects react to more complex gestures, help users
-understand what the outcome will be.</p>
-
-<p>In Recents, when a user starts swiping a thumbnail left or right, it
-begins to dim. This helps the user understand that swiping will cause the
-item to be removed.</p>
-  </div>
-  <div class="col-7">
-
-    <img src="{@docRoot}design/media/touch_feedback_manipulation.png">
-
-  </div>
-</div>
-<div class="vspace size-3">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-6">
-
-    <img src="{@docRoot}design/media/touch_feedback_communication.png">
-    <p><em>If a user attempts to scroll past the last home screen panel, the screen
-    content tilts to the right to indicate that further navigation in this direction
-    isn’t possible.</em></p>
-
-  </div>
-  <div class="col-6">
-
-<h4>Boundaries</h4>
-<p>
-  When users try to scroll past the beginning or end of a scrollable area,
-  communicate the boundary with a visual cue. Many of Android's scrollable UI
-  widgets, like lists and grid lists, have support for boundary feedback built
-  in. If you’re building custom widgets, keep boundary feedback in mind and
-  provide it from within your app.
-</p>
diff --git a/docs/html/design/style/typography.jd b/docs/html/design/style/typography.jd
deleted file mode 100644
index af76c40..0000000
--- a/docs/html/design/style/typography.jd
+++ /dev/null
@@ -1,78 +0,0 @@
-page.title=Typography
-page.tags="textview","font"
-page.metaDescription=How to use typography in your Android apps.
-@jd:body
-
-<div class="cols">
-  <div class="col-8">
-
-    <img src="{@docRoot}design/media/typography_main.png">
-
-  </div>
-
-<a class="notice-designers-material"
-  style="width: 278px;"
-  href="http://www.google.com/design/spec/style/typography.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Typography<p>
-  </div>
-</a>
-
-<div class="col-5">
-
-<p>
-  <a class="download-button"  onClick="ga('send', 'event', 'Design', 'Download', 'Roboto ZIP');"
-    href="{@docRoot}downloads/design/roboto-1.2.zip">Download Roboto</a>
-</p>
-
-<p>The Android design language relies on traditional typographic tools such as scale, space, rhythm,
-and alignment with an underlying grid. Successful deployment of these tools is essential to help
-users quickly understand a screen of information. To support such use of typography, Ice Cream
-Sandwich introduced a new type family named
-<a href="http://www.google.com/fonts/specimen/Roboto" class="external-link">Roboto</a>, created
-specifically for the requirements of UI and high-resolution screens.</p>
-
-<p>The current {@link android.widget.TextView} framework offers Roboto in thin, light, regular and bold
-weights, along with an italic style for each weight. The framework also offers the
-<a href="http://www.google.com/fonts/specimen/Roboto+Condensed" class="external-link">Roboto Condensed</a>
-variant in regular and bold weights, along with an italic style for each weight.</p>
-
-    <img src="{@docRoot}design/media/typography_variants@2x.png" width="220">
-
-<p><a onClick="ga('send', 'event', 'Design', 'Download', 'Roboto Specimen Book (@typography page)');"
-      href="{@docRoot}downloads/design/Roboto_Specimen_Book_20131031.pdf">Specimen Book</a></p>
-
-  </div>
-</div>
-
-<hr>
-
-<div class="cols">
-  <div class="col-6">
-
-<h4>Default type colors</h4>
-<p>The Android UI uses the following default color styles: <code>textColorPrimary</code> and
-<code>textColorSecondary</code>. For light themes use <code>textColorPrimaryInverse</code> and
-<code>textColorSecondaryInverse</code>. The framework text color styles also support variants for
-touch feedback states when used inside UI elements.</p>
-
-    <img src="{@docRoot}design/media/typography_defaults.png">
-
-  </div>
-  <div class="col-6">
-
-<h4>Typographic Scale</h4>
-<p>Contrast in type sizes can go a long way to create ordered, understandable layouts. However, too
-many different sizes in the same UI can be messy. The Android framework uses the following limited
-set of type sizes:</p>
-
-<img src="{@docRoot}design/media/typography_sizes.png">
-
-<p>Users can select a system-wide scaling factor for text in the Settings app. In order to support
-these accessibility features, type should be specified in scale-independent pixels
-(<acronym title="Scale-independent pixels. One sp is one pixel on a 160 dpi screen if the user's global text scale is set to 100%.">sp</acronym>)
-wherever possible. Layouts supporting scalable types should be tested against these settings.</p>
-
-  </div>
-</div>
diff --git a/docs/html/design/style/writing.jd b/docs/html/design/style/writing.jd
deleted file mode 100644
index 0c62a55..0000000
--- a/docs/html/design/style/writing.jd
+++ /dev/null
@@ -1,322 +0,0 @@
-page.title=Writing Style
-page.tags=dialog,toast,notification
-@jd:body
-
-<h2 id="voa">Android's Voice</h2>
-
-<p>When writing text that appears in your app, keep it concise, simple, and friendly.</p>
-
-<h4 id="concise">Concise</h4>
-
-<ul>
-  <li>Describe only what the user needs to know.</li>
-  <li>Eliminate redundancy, such as titles that restate the body of an information box.</li>
-  <li>Keep text as short as possible.</li>
-</ul>
-
-<p><em>Avoid wordy, stilted text</em></p>
-
-<div class="cols">
-  <div class="col-6 layout-with-list-item-margins">
-
-    <div class="do-dont-label bad">Don't</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    Consult the documentation that came with your phone for further instructions.
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="col-6">
-
-    <div class="do-dont-label good">Do</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    Read the instructions that came with your phone.
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-<p><em>Don't provide unnecessary information</em></p>
-
-<div class="cols">
-  <div class="col-6 layout-with-list-item-margins">
-
-    <div class="do-dont-label bad">From a Setup Wizard screen</div>
-
-    <table class="ui-table bad">
-    <thead>
-      <tr>
-        <th>
-        Signing in...
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Your phone needs to communicate with<br>
-        Google servers to sign in to your account.<br>
-        This may take up to five minutes.
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-6">
-
-    <div class="do-dont-label good">From a Setup Wizard screen</div>
-
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th>
-        Signing in...
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Your phone is contacting Google.<br>
-        This can take up to 5 minutes.
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-</div>
-
-<h4 id="simple">Simple</h4>
-
-<ul>
-  <li>Use short words, active verbs, and common nouns.</li>
-  <li>Put the most important thing first. “Front-load” the first 11 characters
-      with the most salient information in the string.</li>
-  <li>Don’t try to explain subtle differences. They are lost on most users.</li>
-</ul>
-
-<p><em>Focus on the user's concern, not technical details</em></p>
-
-<div class="cols">
-  <div class="col-6 layout-with-list-item-margins">
-
-    <div class="do-dont-label bad">Don't</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    Manually control GPS to prevent other apps from using it
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="col-6">
-
-    <div class="do-dont-label good">Do</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    To save power, switch Location mode to Battery saving
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-<p><em>Put top news first</em></p>
-
-<div class="cols">
-  <div class="col-6 layout-with-list-item-margins">
-
-    <div class="do-dont-label bad">Don't</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    77 other people +1’d this, including Larry Page
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="col-6">
-
-    <div class="do-dont-label good">Do</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    Larry Page and 76 others +1’d this
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-<p><em>Put the user's goal first</em></p>
-
-<div class="cols">
-  <div class="col-6 layout-with-list-item-margins">
-
-    <div class="do-dont-label bad">Don't</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    Touch Next to complete setup using a Wi-Fi connection
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="col-6">
-
-    <div class="do-dont-label good">Do</div>
-
-    <table class="ui-table good"><tbody><tr><td>
-    To finish setup using Wi-Fi, touch Next
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-
-<h4 id="friendly">Friendly</h4>
-
-<ul>
-  <li>Use contractions.</li>
-  <li>Talk directly to the reader. Use “you”  to refer to the reader.</li>
-  <li>Keep your tone casual and conversational, but avoid slang.</li>
-</li>
-</ul>
-
-<p><em>Avoid being confusing or annoying</em></p>
-<div class="cols">
-  <div class="col-6 layout-with-list-item-margins">
-    <div class="do-dont-label bad">Don't</div>
-    <table class="ui-table bad">
-    <thead>
-      <tr>
-        <th>
-        Sorry!
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Activity MyAppActivity (in application<br />
-        MyApp) is not responding
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="col-6">
-    <div class="do-dont-label good">Do</div>
-    <table class="ui-table good">
-    <thead>
-      <tr>
-        <th>
-        MyApp isn’t responding 
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Do you want to close it?
-        </td>
-      </tr>
-    </tbody>
-    </table>
-  </div>
-</div>
-
-
-<h4>Words to avoid</h4>
-
-<div style="padding:5px 2.1em;">
-<table>
-  <tr>
-    <td class="do-dont-label bad" style="width:40%">Don't use</td>
-    <td class="do-dont-label good" style="width:40%">Use</td>
-  </tr>
-  <tr>
-    <td>one, two, three, four, ...</td>
-    <td>1, 2, 3, 4, ...</td>
-  </tr>
-  <tr>
-    <td>application</td>
-    <td>app</td>
-  </tr>
-  <tr>
-    <td>cannot, could not, do not, did not 
-will not, you will</td>
-    <td><em>Contractions:</em> can’t, couldn’t, don’t, didn’t won’t, you’ll, and so on</td>
-  </tr>
-    <tr>
-    <td>okay, ok</td>
-    <td>OK</td>
-  </tr>
-  <tr>
-    <td>please, sorry, thank you</td>
-    <td><em>Attempts at politeness can annoy the user, especially in messages that say
-        something has gone wrong.<br />
-        Exception: In Japanese, “please” is mandatory and imperative verbs should
-        be localized accordingly (turn on -> please turn on).
-        </em></td>
-  </tr>
-    <tr>
-    <td>there is, there are, it is<br />
-        <em>and other “disappeared” subjects (grammatical expletives)</em></td>
-    <td><em>Use a noun as the subject</em></td>
-  </tr>
-  <tr>
-    <td>abort, kill, terminate</td>
-    <td>stop, cancel, end, exit</td>
-  </tr>
-    <tr>
-    <td>fail, failed, <em>negative language</em></td>
-    <td><em>In general, use positive phrasing<br />
-        (for example, “do” rather than “don’t,” except in cases such as “Don’t show
-        again,” “Can’t connect,” and so on.)</em></td>
-  </tr>
-  <tr>
-    <td>me, I, my, mine</td>
-    <td>you, your, yours</td>
-  </tr>
-    <tr>
-    <td>Are you sure? Warning!</td>
-    <td><em>Tell user the consequence instead, for example, “You’ll lose all photos 
-        and media”</em></td>
-  </tr>
-</table>
-
-</div>
-
-<h2 id="formatting_text">Formatting text</h2>
-
-<h4 id="capitalization">Capitalization</h4>
-
-<ul>
-  <li>Use sentence-style capitalization for all UI strings: “Words to live by.”</li>
-  <li>Capitalize all important words in: 
-    <ul>
-      <li>App names (Calendar, Google Drive)</li>
-      <li>Named features (Android Beam, Face Unlock)</li>
-      <li>Proper nouns (Statue of Liberty, San Francisco Giants)</li>
-    </ul>
-  </li>
-  <li>Be conservative. Don't capitalize words that aren't part of a formal feature name: 
-    <ul>
-      <li>Sim card lock, Home screen, not Sim Card Lock, Home Screen.</li>
-    </ul>
-  </li>
-</ul>
-
-
-<h4 id="punctuation">Punctuation</h4>
-<ul>
-  <li><strong>Period.</strong> Don't use a period after a single sentence or
-  phrase used in isolation, such as in a toast, label, or notification. Wherever two or
-  more sentences run together, use a period for each sentence. </li>
-  <li><strong>Ellipsis.</strong> Use the ellipsis character (…) (Option-; on MacOS and &amp;hellip;
-    in HTML) to indicate 
-    <ul>
-      <li>Incompleteness, such as an action in progress (“Downloading...”) or truncated text.</li>
-      <li>That a menu item (such as Print… or Share…) leads to further UI involving significant
-        choices. Exception: Commands whose wording already implies further (but limited) UI, such
-        as <strong>Find in page</strong> or <strong>Pick a date</strong>, do not require an
-        ellipsis. </li>
-    </ul>
-  </li>
-</ul>
diff --git a/docs/html/design/videos/index.jd b/docs/html/design/videos/index.jd
deleted file mode 100644
index 3845b44..0000000
--- a/docs/html/design/videos/index.jd
+++ /dev/null
@@ -1,130 +0,0 @@
-page.title=Videos
-@jd:body
-
-<p>The Android Design Team presents design-oriented sessions at Google I/O every year. Visit these pages to view the videos and presentations from the conferences.</p>
-
-<img src="{@docRoot}images/home/io-logo-2013-alt.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326368573">Enchant, Simplify, Amaze: Android's Design Principles</a></h3>
-    <p>Want to enchant people, simplify their lives, and make them feel amazing with your app? Learn how Android's Design Principles can help you create products that resonate with people. Find out about the meaning and research behind the principles. See real-world examples and practices from the Android Design team. Discover techniques for applying the principles in your daily work. No design experience necessary.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/s0HIP8EdlnE" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326301704">Structure in Android App Design</a></h3>
-    <p>Life is simple when your app is simple. But when your apps gets more complex, how do you choose between spinners, tabs, and drawers for navigation? Members of the Android Design team look at techniques for making your app predictable and pleasing to use.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/XpqyiBR0lJ4" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326425499">Fireside Chat with the Android Team</a></h3>
-    <p>Pull up a chair and join the Android platform team for a fireside chat. It's your opportunity to ask us about the platform and learn a little bit more about why things work the way they do, from the people who built it. </p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/A5OOJDIrYls" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326483138">Agile UX Research Practice in Android</a></h3>
-    <p>In the Android UX team, it is critical to get user feedback frequently and consistently so that we are able to iterate and develop the best-in-class designs for our users. We will discuss how the team applied "Pulse Studies" (iterative research sessions) in order to put new ideas, designs, and concepts in front of users on a regular basis; it requires minimal advance planning, it can have an immediate product impact, and it can meet urgent needs. </p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/6MOeVNbh9cY" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-success"><a href="https://developers.google.com/events/io/2013/sessions/326460111">Cognitive Science and Design</a></h3>
-    <p>This session will provide an in-depth look at human perception and cognition, and its implications for interactive and visual design. The human brain is purely treated as an information processing machine, and we will teach the audience its attributes, its advantages, its limitations, and generally how to hack it. </p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/z2exxj4COhU" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<img src="{@docRoot}design/media/extras_googleio_12.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-success"><a href="https://developers.google.com/events/io/sessions/gooio2012/112/">Android Design for Success</a></h3>
-    <p>You have a great idea for an Android app. You want it to stand out among hundreds of thousands. You want your users to love it and tell everyone they know. The Android User Experience team is here to help. We talk about the Android Design guide and other tricks of the trade for creating apps that delight users and help them accomplish their goals. No design background is required.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/2NL_83EG0no" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="design-for-engineers"><a href="https://developers.google.com/events/io/sessions/gooio2012/1204/">Android Design for Engineers</a></h3>
-    <p>Design isn't black magic, it's a field that people can learn. In this talk two elite designers from Google give you an advanced crash course in interactive and visual design. Topics include mental models, natural mappings, metaphors, mode errors, visual hierarchies, typography and gestalt principles. Correctly applied, this knowledge can drastically improve the quality of your work.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/iJDoxOTyMdk" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="navigation-in-android"><a href="https://developers.google.com/events/io/sessions/gooio2012/114/">Navigation in Android</a></h3>
-    <p>An app is useless if people can't find their way around it. Android introduced big navigation-support changes in 3.0 and 4.0. The Action Bar offers a convenient control for Up navigation, the Back key's behavior became more consistent within tasks, and the Recent Tasks UI got an overhaul. In this talk, we discuss how and why we got where we are today, how to think about navigation when designing your app's user experience, and how to write apps that offer effortless navigation in multiple Android versions.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/XwGHJJYBs0Q" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="now-what"><a href="https://developers.google.com/events/io/sessions/gooio2012/115/">So You've Read the Design Guide&#59; Now What?</a></h3>
-    <p>The Android Design Guide describes how to design beautiful Android apps, but not how to build them. In this talk we give practical tips for how to apply fit &amp; finish as you implement your design, we show you how to avoid some common pitfalls, we describe some useful patterns, and show how tools can help.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/2jCVmfCse1E" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="cols">
-  <div class="col-7">
-    <h3 id="playing-with-patterns"><a href="https://developers.google.com/events/io/sessions/gooio2012/131/">Playing with Patterns</a></h3>
-    <p>Best-in-class application designers and developers talk about their experience in developing for Android, showing screenshots from their app, exploring the challenges they faced, and offering creative solutions congruent with the Android Design guide. Guests are invited to show examples of visual and interaction patterns in their application that manage to keep it simultaneously consistent and personal.</p>
-  </div>
-  <div class="col-6">
-    <iframe width="355" height="200" src="//www.youtube.com/embed/8iUbr8RZKtg" frameborder="0" allowfullscreen=""></iframe>
-  </div>
-</div>
-
-<p>Videos for the entire Design Track can also be found on the <a href="http://www.youtube.com/playlist?list=PL54FA004D676C3EE9">Android Developers Channel</a> on YouTube.</p>
diff --git a/docs/html/guide/topics/renderscript/reference.jd b/docs/html/guide/topics/renderscript/reference.jd
deleted file mode 100644
index a9d780a..0000000
--- a/docs/html/guide/topics/renderscript/reference.jd
+++ /dev/null
@@ -1,21 +0,0 @@
-page.title=Runtime API Reference
-parent.title=Computation
-parent.link=index.html
-
-@jd:body
-
-<script language="JavaScript">
-
-function autoResize(element){
-    var newheight;
-    var newwidth;
-
-    newheight = element.contentWindow.document.body.scrollHeight + 20;
-    newwidth = element.contentWindow.document.body.scrollWidth;
-    element.height = (newheight) + "px";
-    element.width = (newwidth) + "px";
-}
-</script>
-
-
-<iframe SRC="{@docRoot}reference/renderscript/index.html" width="100%"  id="iframe" marginheight="0" frameborder="0" onLoad="autoResize(this);"></iframe>
diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd
index 217db81..fea3b2c 100644
--- a/docs/html/training/articles/keystore.jd
+++ b/docs/html/training/articles/keystore.jd
@@ -129,7 +129,7 @@
   for use as soon as the user unlocks the secure lock screen or confirms their secure lock screen
   credentials using the {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent}
   flow. Each key specifies for how long the authorization remains valid for that key. Such keys
-  can only be generated or imported if the secure lock screen is enabled (see {@link android.app.KeyguardManager#isKeyguardSecure Keyguard.isKeyguardSecure}).
+  can only be generated or imported if the secure lock screen is enabled (see {@link android.app.KeyguardManager#isDeviceSecure()}).
   These keys become permanently invalidated once the secure lock screen is disabled or forcibly
   reset (e.g. by a Device Admin).</li>
 <li>User authentication is required for every use of the key. In this mode, a specific operation
diff --git a/graphics/java/android/graphics/Atlas.java b/graphics/java/android/graphics/Atlas.java
index 39a5a53..e0a5345 100644
--- a/graphics/java/android/graphics/Atlas.java
+++ b/graphics/java/android/graphics/Atlas.java
@@ -21,10 +21,12 @@
  */
 public class Atlas {
     /**
-     * This flag indicates whether the packing algorithm will attempt
-     * to rotate entries to make them fit better in the atlas.
+     * WARNING: These flag values are part of the on-disk configuration information,
+     * do not change their values.
      */
-    public static final int FLAG_ALLOW_ROTATIONS = 0x1;
+
+    /** DELETED: FLAG_ROTATION = 0x01 */
+
     /**
      * This flag indicates whether the packing algorithm should leave
      * an empty 1 pixel wide border around each bitmap. This border can
@@ -52,9 +54,7 @@
 
     /**
      * Represents a bitmap packed in the atlas. Each entry has a location in
-     * pixels in the atlas and a rotation flag. If the entry was rotated, the
-     * bitmap must be rotated by 90 degrees (in either direction as long as
-     * the origin remains the same) before being rendered into the atlas.
+     * pixels in the atlas and a rotation flag.
      */
     public static class Entry {
         /**
@@ -65,11 +65,6 @@
          * Location, in pixels, of the bitmap on the Y axis in the atlas.
          */
         public int y;
-
-        /**
-         * If true, the bitmap must be rotated 90 degrees in the atlas.
-         */
-        public boolean rotated;
     }
 
     private final Policy mPolicy;
@@ -239,7 +234,6 @@
 
         private final SplitDecision mSplitDecision;
 
-        private final boolean mAllowRotation;
         private final int mPadding;
 
         /**
@@ -263,7 +257,6 @@
         }
 
         SlicePolicy(int width, int height, int flags, SplitDecision splitDecision) {
-            mAllowRotation = (flags & FLAG_ALLOW_ROTATIONS) != 0;
             mPadding = (flags & FLAG_ADD_PADDING) != 0 ? 1 : 0;
 
             // The entire atlas is empty at first, minus padding
@@ -360,26 +353,9 @@
          *
          * @return True if the rectangle was packed in the atlas, false otherwise
          */
-        @SuppressWarnings("SuspiciousNameCombination")
         private boolean insert(Cell cell, Cell prev, int width, int height, Entry entry) {
-            boolean rotated = false;
-
-            // If the rectangle doesn't fit we'll try to rotate it
-            // if possible before giving up
             if (cell.width < width || cell.height < height) {
-                if (mAllowRotation) {
-                    if (cell.width < height || cell.height < width) {
-                        return false;
-                    }
-
-                    // Rotate the rectangle
-                    int temp = width;
-                    width = height;
-                    height = temp;
-                    rotated = true;
-                } else {
-                    return false;
-                }
+                return false;
             }
 
             // Remaining free space after packing the rectangle
@@ -433,7 +409,6 @@
             // Return the location and rotation of the packed rectangle
             entry.x = cell.x;
             entry.y = cell.y;
-            entry.rotated = rotated;
 
             return true;
         }
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c850b07..bd52848 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -330,6 +330,7 @@
      * @return The current generation ID for this bitmap.
      */
     public int getGenerationId() {
+        if (mRecycled) return 0;
         return nativeGenerationId(mFinalizer.mNativeBitmap);
     }
 
@@ -1040,6 +1041,7 @@
      * @see BitmapFactory.Options#inPremultiplied
      */
     public final boolean isPremultiplied() {
+        if (mRecycled) return false;
         return nativeIsPremultiplied(mFinalizer.mNativeBitmap);
     }
 
@@ -1064,6 +1066,7 @@
      * @see BitmapFactory.Options#inPremultiplied
      */
     public final void setPremultiplied(boolean premultiplied) {
+        checkRecycled("setPremultiplied called on a recycled bitmap");
         mRequestPremultiplied = premultiplied;
         nativeSetPremultiplied(mFinalizer.mNativeBitmap, premultiplied);
     }
@@ -1200,6 +1203,7 @@
      * that config, otherwise return null.
      */
     public final Config getConfig() {
+        if (mRecycled) return Config.ARGB_8888;
         return Config.nativeToConfig(nativeConfig(mFinalizer.mNativeBitmap));
     }
 
@@ -1212,6 +1216,7 @@
      * it will return true by default.
      */
     public final boolean hasAlpha() {
+        if (mRecycled) return false;
         return nativeHasAlpha(mFinalizer.mNativeBitmap);
     }
 
@@ -1226,6 +1231,7 @@
      * non-opaque per-pixel alpha values.
      */
     public void setHasAlpha(boolean hasAlpha) {
+        checkRecycled("setHasAlpha called on a recycled bitmap");
         nativeSetHasAlpha(mFinalizer.mNativeBitmap, hasAlpha, mRequestPremultiplied);
     }
 
@@ -1247,6 +1253,7 @@
      * @see #setHasMipMap(boolean)
      */
     public final boolean hasMipMap() {
+        if (mRecycled) return false;
         return nativeHasMipMap(mFinalizer.mNativeBitmap);
     }
 
@@ -1271,6 +1278,7 @@
      * @see #hasMipMap()
      */
     public final void setHasMipMap(boolean hasMipMap) {
+        checkRecycled("setHasMipMap called on a recycled bitmap");
         nativeSetHasMipMap(mFinalizer.mNativeBitmap, hasMipMap);
     }
 
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 587e7fa..b15caeb 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1631,6 +1631,7 @@
 
         status_t applyStyle(uint32_t resID, bool force=false);
         status_t setTo(const Theme& other);
+        status_t clear();
 
         /**
          * Retrieve a value in the theme.  If the theme defines this
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java
index 3b25ba6..3f29c6a 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("RSA");
+            super(KeyStoreKeyProperties.Algorithm.RSA);
         }
     }
 
     public static class EC extends AndroidKeyPairGenerator {
         public EC() {
-            super("EC");
+            super(KeyStoreKeyProperties.Algorithm.EC);
         }
     }
 
@@ -83,15 +83,15 @@
     private android.security.KeyStore mKeyStore;
 
     private KeyPairGeneratorSpec mSpec;
-    private String mKeyAlgorithm;
+    private @KeyStoreKeyProperties.AlgorithmEnum String mKeyAlgorithm;
     private int mKeyType;
     private int mKeySize;
 
-    protected AndroidKeyPairGenerator(String algorithm) {
+    protected AndroidKeyPairGenerator(@KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
         mAlgorithm = algorithm;
     }
 
-    public String getAlgorithm() {
+    public @KeyStoreKeyProperties.AlgorithmEnum String getAlgorithm() {
         return mAlgorithm;
     }
 
@@ -197,7 +197,7 @@
         return certGen.generate(privateKey);
     }
 
-    private String getKeyAlgorithm(KeyPairGeneratorSpec spec) {
+    private @KeyStoreKeyProperties.AlgorithmEnum String getKeyAlgorithm(KeyPairGeneratorSpec spec) {
         String result = spec.getKeyType();
         if (result != null) {
             return result;
@@ -248,10 +248,11 @@
         }
     }
 
-    private static String getDefaultSignatureAlgorithmForKeyAlgorithm(String algorithm) {
-        if ("RSA".equalsIgnoreCase(algorithm)) {
+    private static String getDefaultSignatureAlgorithmForKeyAlgorithm(
+            @KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
+        if (KeyStoreKeyProperties.Algorithm.RSA.equalsIgnoreCase(algorithm)) {
             return "sha256WithRSA";
-        } else if ("EC".equalsIgnoreCase(algorithm)) {
+        } else if (KeyStoreKeyProperties.Algorithm.EC.equalsIgnoreCase(algorithm)) {
             return "sha256WithECDSA";
         } else {
             throw new IllegalArgumentException("Unsupported key type " + algorithm);
@@ -287,7 +288,7 @@
         }
 
         KeyPairGeneratorSpec spec = (KeyPairGeneratorSpec) params;
-        String keyAlgorithm = getKeyAlgorithm(spec);
+        @KeyStoreKeyProperties.AlgorithmEnum 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 72cb062..e82ff6a 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -128,10 +128,11 @@
                 keymasterDigest = keymasterDigests.get(0);
             }
 
-            String keyAlgorithmString;
+            @KeyStoreKeyProperties.AlgorithmEnum String keyAlgorithmString;
             try {
-                keyAlgorithmString = KeymasterUtils.getJcaSecretKeyAlgorithm(
-                        keymasterAlgorithm, keymasterDigest);
+                keyAlgorithmString =
+                        KeyStoreKeyProperties.Algorithm.fromKeymasterSecretKeyAlgorithm(
+                                keymasterAlgorithm, keymasterDigest);
             } catch (IllegalArgumentException e) {
                 throw (UnrecoverableKeyException)
                         new UnrecoverableKeyException("Unsupported secret key type").initCause(e);
@@ -451,10 +452,10 @@
         int keymasterAlgorithm;
         int keymasterDigest;
         try {
-            keymasterAlgorithm = KeymasterUtils.getKeymasterAlgorithmFromJcaSecretKeyAlgorithm(
+            keymasterAlgorithm = KeyStoreKeyProperties.Algorithm.toKeymasterSecretKeyAlgorithm(
                     keyAlgorithmString);
             keymasterDigest =
-                    KeymasterUtils.getKeymasterDigestfromJcaSecretKeyAlgorithm(keyAlgorithmString);
+                    KeyStoreKeyProperties.Algorithm.toKeymasterDigest(keyAlgorithmString);
         } catch (IllegalArgumentException e) {
             throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString);
         }
@@ -465,8 +466,7 @@
         int[] keymasterDigests;
         if (params.isDigestsSpecified()) {
             // Digest(s) specified in parameters
-            keymasterDigests =
-                    KeymasterUtils.getKeymasterDigestsFromJcaDigestAlgorithms(params.getDigests());
+            keymasterDigests = KeyStoreKeyProperties.Digest.allToKeymaster(params.getDigests());
             if (keymasterDigest != -1) {
                 // Digest also specified in the JCA key algorithm name.
                 if (!com.android.internal.util.ArrayUtils.contains(
@@ -494,8 +494,8 @@
         }
 
         @KeyStoreKeyProperties.PurposeEnum int purposes = params.getPurposes();
-        int[] keymasterBlockModes = KeymasterUtils.getKeymasterBlockModesFromJcaBlockModes(
-                params.getBlockModes());
+        int[] keymasterBlockModes =
+                KeyStoreKeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
         if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
                 && (params.isRandomizedEncryptionRequired())) {
             for (int keymasterBlockMode : keymasterBlockModes) {
@@ -503,8 +503,7 @@
                     throw new KeyStoreException(
                             "Randomized encryption (IND-CPA) required but may be violated by block"
                             + " mode: "
-                            + KeymasterUtils.getJcaBlockModeFromKeymasterBlockMode(
-                                    keymasterBlockMode)
+                            + KeyStoreKeyProperties.BlockMode.fromKeymaster(keymasterBlockMode)
                             + ". See KeyStoreParameter documentation.");
                 }
             }
@@ -513,11 +512,11 @@
             args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose);
         }
         args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
-        int[] keymasterPaddings = ArrayUtils.concat(
-                KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings(
-                        params.getEncryptionPaddings()),
-                KeymasterUtils.getKeymasterPaddingsFromJcaSignaturePaddings(
-                        params.getSignaturePaddings()));
+        if (params.getSignaturePaddings().length > 0) {
+            throw new KeyStoreException("Signature paddings not supported for symmetric keys");
+        }
+        int[] keymasterPaddings = KeyStoreKeyProperties.EncryptionPadding.allToKeymaster(
+                params.getEncryptionPaddings());
         args.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
         KeymasterUtils.addUserAuthArgs(args,
                 params.getContext(),
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index e9c24dd..8e27dc3 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -262,7 +262,8 @@
      *     unavailable.
      */
     public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
-            String[] keyTypes, Principal[] issuers, String host, int port, String alias) {
+            @KeyStoreKeyProperties.AlgorithmEnum String[] keyTypes, Principal[] issuers,
+            String host, int port, String alias) {
         choosePrivateKeyAlias(activity, response, keyTypes, issuers, host, port, null, alias);
     }
 
@@ -306,9 +307,8 @@
      *     unavailable.
      */
     public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
-                                             String[] keyTypes, Principal[] issuers,
-                                             String host, int port, String url,
-                                             String alias) {
+            @KeyStoreKeyProperties.AlgorithmEnum String[] keyTypes, Principal[] issuers,
+            String host, int port, String url, String alias) {
         /*
          * TODO currently keyTypes, issuers are unused. They are meant
          * to follow the semantics and purpose of X509KeyManager
@@ -431,9 +431,11 @@
      * specific {@code PrivateKey} type indicated by {@code algorithm} (e.g.,
      * "RSA").
      */
-    public static boolean isKeyAlgorithmSupported(String algorithm) {
+    public static boolean isKeyAlgorithmSupported(
+            @KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
         final String algUpper = algorithm.toUpperCase(Locale.US);
-        return "EC".equals(algUpper) || "RSA".equals(algUpper);
+        return KeyStoreKeyProperties.Algorithm.EC.equals(algUpper)
+                || KeyStoreKeyProperties.Algorithm.RSA.equals(algUpper);
     }
 
     /**
@@ -443,7 +445,8 @@
      * hardware support that can be used to bind keys to the device in a way
      * that makes it non-exportable.
      */
-    public static boolean isBoundKeyAlgorithm(String algorithm) {
+    public static boolean isBoundKeyAlgorithm(
+            @KeyStoreKeyProperties.AlgorithmEnum String algorithm) {
         if (!isKeyAlgorithmSupported(algorithm)) {
             return false;
         }
diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java
index 8f135a6..729646d 100644
--- a/keystore/java/android/security/KeyGeneratorSpec.java
+++ b/keystore/java/android/security/KeyGeneratorSpec.java
@@ -48,8 +48,8 @@
     private final Date mKeyValidityForOriginationEnd;
     private final Date mKeyValidityForConsumptionEnd;
     private final @KeyStoreKeyProperties.PurposeEnum int mPurposes;
-    private final String[] mEncryptionPaddings;
-    private final String[] mBlockModes;
+    private final @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
+    private final @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
     private final boolean mRandomizedEncryptionRequired;
     private final boolean mUserAuthenticationRequired;
     private final int mUserAuthenticationValidityDurationSeconds;
@@ -63,8 +63,8 @@
             Date keyValidityForOriginationEnd,
             Date keyValidityForConsumptionEnd,
             @KeyStoreKeyProperties.PurposeEnum int purposes,
-            String[] encryptionPaddings,
-            String[] blockModes,
+            @KeyStoreKeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
+            @KeyStoreKeyProperties.BlockModeEnum String[] blockModes,
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds) {
@@ -160,14 +160,14 @@
     /**
      * Gets the set of padding schemes with which the key can be used when encrypting/decrypting.
      */
-    public String[] getEncryptionPaddings() {
+    public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
         return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings);
     }
 
     /**
      * Gets the set of block modes with which the key can be used.
      */
-    public String[] getBlockModes() {
+    public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
         return ArrayUtils.cloneIfNotEmpty(mBlockModes);
     }
 
@@ -195,10 +195,12 @@
 
     /**
      * Gets the duration of time (seconds) for which this key can be used after the user is
-     * successfully authenticated.
+     * successfully authenticated. This has effect only if user authentication is required.
      *
-     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
-     *         is required for every use of the key.
+     * @return duration in seconds or {@code -1} if authentication is required for every use of the
+     *         key.
+     *
+     * @see #isUserAuthenticationRequired()
      */
     public int getUserAuthenticationValidityDurationSeconds() {
         return mUserAuthenticationValidityDurationSeconds;
@@ -220,8 +222,8 @@
         private Date mKeyValidityForOriginationEnd;
         private Date mKeyValidityForConsumptionEnd;
         private @KeyStoreKeyProperties.PurposeEnum int mPurposes;
-        private String[] mEncryptionPaddings;
-        private String[] mBlockModes;
+        private @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
+        private @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
         private boolean mRandomizedEncryptionRequired = true;
         private boolean mUserAuthenticationRequired;
         private int mUserAuthenticationValidityDurationSeconds = -1;
@@ -346,7 +348,8 @@
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
          */
-        public Builder setEncryptionPaddings(String... paddings) {
+        public Builder setEncryptionPaddings(
+                @KeyStoreKeyProperties.EncryptionPaddingEnum String... paddings) {
             mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings);
             return this;
         }
@@ -357,7 +360,7 @@
          *
          * <p>This must be specified for encryption/decryption keys.
          */
-        public Builder setBlockModes(String... blockModes) {
+        public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
             mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes);
             return this;
         }
@@ -425,7 +428,7 @@
          *
          * <p>By default, the user needs to authenticate for every use of the key.
          *
-         * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
+         * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
          *        every use of the key.
          *
          * @see #setUserAuthenticationRequired(boolean)
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index d6d3789..25c61fd 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -85,13 +85,13 @@
 
     private final @KeyStoreKeyProperties.PurposeEnum int mPurposes;
 
-    private final String[] mDigests;
+    private final @KeyStoreKeyProperties.DigestEnum String[] mDigests;
 
-    private final String[] mEncryptionPaddings;
+    private final @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
 
-    private final String[] mSignaturePaddings;
+    private final @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
 
-    private final String[] mBlockModes;
+    private final @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
 
     private final boolean mRandomizedEncryptionRequired;
 
@@ -138,10 +138,10 @@
             Date keyValidityForOriginationEnd,
             Date keyValidityForConsumptionEnd,
             @KeyStoreKeyProperties.PurposeEnum int purposes,
-            String[] digests,
-            String[] encryptionPaddings,
-            String[] signaturePaddings,
-            String[] blockModes,
+            @KeyStoreKeyProperties.DigestEnum String[] digests,
+            @KeyStoreKeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
+            @KeyStoreKeyProperties.SignaturePaddingEnum String[] signaturePaddings,
+            @KeyStoreKeyProperties.BlockModeEnum String[] blockModes,
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds) {
@@ -246,7 +246,7 @@
     /**
      * Returns the key type (e.g., "EC", "RSA") specified by this parameter.
      */
-    public String getKeyType() {
+    public @KeyStoreKeyProperties.AlgorithmEnum String getKeyType() {
         return mKeyType;
     }
 
@@ -352,28 +352,28 @@
     /**
      * Gets the set of digest algorithms with which the key can be used.
      */
-    public String[] getDigests() {
+    public @KeyStoreKeyProperties.DigestEnum String[] getDigests() {
         return ArrayUtils.cloneIfNotEmpty(mDigests);
     }
 
     /**
      * Gets the set of padding schemes with which the key can be used when encrypting/decrypting.
      */
-    public String[] getEncryptionPaddings() {
+    public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
         return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings);
     }
 
     /**
      * Gets the set of padding schemes with which the key can be used when signing/verifying.
      */
-    public String[] getSignaturePaddings() {
+    public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
         return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings);
     }
 
     /**
      * Gets the set of block modes with which the key can be used.
      */
-    public String[] getBlockModes() {
+    public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
         return ArrayUtils.cloneIfNotEmpty(mBlockModes);
     }
 
@@ -403,14 +403,14 @@
     }
 
     /**
-     * Gets the duration of time (seconds) for which the private key can be used after the user
-     * is successfully authenticated.
+     * Gets the duration of time (seconds) for which this key can be used after the user is
+     * successfully authenticated. This has effect only if user authentication is required.
      *
      * <p>This restriction applies only to private key operations. Public key operations are not
      * restricted.
      *
-     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
-     *         is required for every use of the key.
+     * @return duration in seconds or {@code -1} if authentication is required for every use of the
+     *         key.
      *
      * @see #isUserAuthenticationRequired()
      */
@@ -468,13 +468,13 @@
 
         private @KeyStoreKeyProperties.PurposeEnum int mPurposes;
 
-        private String[] mDigests;
+        private @KeyStoreKeyProperties.DigestEnum String[] mDigests;
 
-        private String[] mEncryptionPaddings;
+        private @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
 
-        private String[] mSignaturePaddings;
+        private @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
 
-        private String[] mBlockModes;
+        private @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
 
         private boolean mRandomizedEncryptionRequired = true;
 
@@ -511,7 +511,8 @@
         /**
          * Sets the key type (e.g., EC, RSA) of the keypair to be created.
          */
-        public Builder setKeyType(String keyType) throws NoSuchAlgorithmException {
+        public Builder setKeyType(@KeyStoreKeyProperties.AlgorithmEnum String keyType)
+                throws NoSuchAlgorithmException {
             if (keyType == null) {
                 throw new NullPointerException("keyType == null");
             } else {
@@ -628,6 +629,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect.
+         *
          * @see #setKeyValidityEnd(Date)
          */
         public Builder setKeyValidityStart(Date startDate) {
@@ -640,6 +643,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect.
+         *
          * @see #setKeyValidityStart(Date)
          * @see #setKeyValidityForConsumptionEnd(Date)
          * @see #setKeyValidityForOriginationEnd(Date)
@@ -655,6 +660,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect.
+         *
          * @see #setKeyValidityForConsumptionEnd(Date)
          */
         public Builder setKeyValidityForOriginationEnd(Date endDate) {
@@ -668,6 +675,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect.
+         *
          * @see #setKeyValidityForOriginationEnd(Date)
          */
         public Builder setKeyValidityForConsumptionEnd(Date endDate) {
@@ -679,6 +688,8 @@
          * Sets the set of purposes for which the key can be used.
          *
          * <p>This must be specified for all keys. There is no default.
+         *
+         * <p><b>NOTE: This has currently no effect.
          */
         public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) {
             mPurposes = purposes;
@@ -690,8 +701,10 @@
          * to use the key with any other digest will be rejected.
          *
          * <p>This must be specified for keys which are used for signing/verification.
+         *
+         * <p><b>NOTE: This has currently no effect.
          */
-        public Builder setDigests(String... digests) {
+        public Builder setDigests(@KeyStoreKeyProperties.DigestEnum String... digests) {
             mDigests = ArrayUtils.cloneIfNotEmpty(digests);
             return this;
         }
@@ -702,8 +715,11 @@
          * rejected.
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
+         *
+         * <p><b>NOTE: This has currently no effect.
          */
-        public Builder setEncryptionPaddings(String... paddings) {
+        public Builder setEncryptionPaddings(
+                @KeyStoreKeyProperties.EncryptionPaddingEnum String... paddings) {
             mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings);
             return this;
         }
@@ -714,8 +730,11 @@
          * rejected.
          *
          * <p>This must be specified for RSA keys which are used for signing/verification.
+         *
+         * <p><b>NOTE: This has currently no effect.
          */
-        public Builder setSignaturePaddings(String... paddings) {
+        public Builder setSignaturePaddings(
+                @KeyStoreKeyProperties.SignaturePaddingEnum String... paddings) {
             mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(paddings);
             return this;
         }
@@ -725,8 +744,10 @@
          * 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.
          */
-        public Builder setBlockModes(String... blockModes) {
+        public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
             mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes);
             return this;
         }
@@ -750,6 +771,8 @@
          * <li>If you are using RSA encryption without padding, consider switching to padding
          * schemes which offer {@code IND-CPA}, such as PKCS#1 or OAEP.</li>
          * </ul>
+         *
+         * <p><b>NOTE: This has currently no effect.
          */
         public Builder setRandomizedEncryptionRequired(boolean required) {
             mRandomizedEncryptionRequired = required;
@@ -772,6 +795,8 @@
          * <p>This restriction applies only to private key operations. Public key operations are not
          * restricted.
          *
+         * <p><b>NOTE: This has currently no effect.
+         *
          * @see #setUserAuthenticationValidityDurationSeconds(int)
          */
         public Builder setUserAuthenticationRequired(boolean required) {
@@ -788,7 +813,9 @@
          * <p>This restriction applies only to private key operations. Public key operations are not
          * restricted.
          *
-         * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
+         * <p><b>NOTE: This has currently no effect.
+         *
+         * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
          *        every use of the key.
          *
          * @see #setUserAuthenticationRequired(boolean)
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 82d328b..304d277 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -115,10 +115,10 @@
         return mToken;
     }
 
-    static int getKeyTypeForAlgorithm(String keyType) {
-        if ("RSA".equalsIgnoreCase(keyType)) {
+    static int getKeyTypeForAlgorithm(@KeyStoreKeyProperties.AlgorithmEnum String keyType) {
+        if (KeyStoreKeyProperties.Algorithm.RSA.equalsIgnoreCase(keyType)) {
             return NativeConstants.EVP_PKEY_RSA;
-        } else if ("EC".equalsIgnoreCase(keyType)) {
+        } else if (KeyStoreKeyProperties.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 094aa75..bd601bc 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -27,6 +27,7 @@
 import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
@@ -315,15 +316,15 @@
             } else if (e instanceof InvalidAlgorithmParameterException) {
                 throw (InvalidAlgorithmParameterException) e;
             } else {
-                throw new RuntimeException("Unexpected exception type", e);
+                throw new ProviderException("Unexpected exception type", e);
             }
         }
 
         if (mOperationToken == null) {
-            throw new IllegalStateException("Keystore returned null operation token");
+            throw new ProviderException("Keystore returned null operation token");
         }
         if (mOperationHandle == 0) {
-            throw new IllegalStateException("Keystore returned invalid operation handle");
+            throw new ProviderException("Keystore returned invalid operation handle");
         }
 
         loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
@@ -494,13 +495,14 @@
         }
         if ((mIv != null) && (mIv.length > 0)) {
             try {
-                AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
+                AlgorithmParameters params =
+                        AlgorithmParameters.getInstance(KeyStoreKeyProperties.Algorithm.AES);
                 params.init(new IvParameterSpec(mIv));
                 return params;
             } catch (NoSuchAlgorithmException e) {
-                throw new RuntimeException("Failed to obtain AES AlgorithmParameters", e);
+                throw new ProviderException("Failed to obtain AES AlgorithmParameters", e);
             } catch (InvalidParameterSpecException e) {
-                throw new RuntimeException(
+                throw new ProviderException(
                         "Failed to initialize AES AlgorithmParameters with an IV", e);
             }
         }
@@ -633,10 +635,9 @@
                 if ((mIv == null) && (mEncrypting)) {
                     // IV was not provided by the caller and thus will be generated by keymaster.
                     // Mix in some additional entropy from the provided SecureRandom.
-                    if (mRng != null) {
-                        mAdditionalEntropyForBegin = new byte[mBlockSizeBytes];
-                        mRng.nextBytes(mAdditionalEntropyForBegin);
-                    }
+                    mAdditionalEntropyForBegin =
+                            KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
+                                    mRng, mBlockSizeBytes);
                 }
             }
         }
@@ -668,11 +669,11 @@
             if (mIv == null) {
                 mIv = returnedIv;
             } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
-                throw new IllegalStateException("IV in use differs from provided IV");
+                throw new ProviderException("IV in use differs from provided IV");
             }
         } else {
             if (returnedIv != null) {
-                throw new IllegalStateException(
+                throw new ProviderException(
                         "IV in use despite IV not being used by this transformation");
             }
         }
diff --git a/keystore/java/android/security/KeyStoreConnectException.java b/keystore/java/android/security/KeyStoreConnectException.java
index 1aa3aec..885f1f7 100644
--- a/keystore/java/android/security/KeyStoreConnectException.java
+++ b/keystore/java/android/security/KeyStoreConnectException.java
@@ -16,12 +16,14 @@
 
 package android.security;
 
+import java.security.ProviderException;
+
 /**
  * Indicates a communications error with keystore service.
  *
  * @hide
  */
-public class KeyStoreConnectException extends IllegalStateException {
+public class KeyStoreConnectException extends ProviderException {
     public KeyStoreConnectException() {
         super("Failed to communicate with keystore service");
     }
diff --git a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
index e5933ad..311278b 100644
--- a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
+++ b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
@@ -21,6 +21,7 @@
 import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
+import java.security.SecureRandom;
 
 /**
  * Assorted utility methods for implementing crypto operations on top of KeyStore.
@@ -28,6 +29,9 @@
  * @hide
  */
 abstract class KeyStoreCryptoOperationUtils {
+
+    private static volatile SecureRandom sRng;
+
     private KeyStoreCryptoOperationUtils() {}
 
     /**
@@ -81,4 +85,28 @@
         // General cases
         return getInvalidKeyExceptionForInit(keyStore, key, beginOpResultCode);
     }
+
+    /**
+     * Returns the requested number of random bytes to mix into keystore/keymaster RNG.
+     *
+     * @param rng RNG from which to obtain the random bytes or {@code null} for the platform-default
+     *        RNG.
+     */
+    static byte[] getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes) {
+        if (rng == null) {
+            rng = getRng();
+        }
+        byte[] result = new byte[sizeBytes];
+        rng.nextBytes(result);
+        return result;
+    }
+
+    private static SecureRandom getRng() {
+        // IMPLEMENTATION NOTE: It's OK to share a SecureRandom instance because SecureRandom is
+        // required to be thread-safe.
+        if (sRng == null) {
+            sRng = new SecureRandom();
+        }
+        return sRng;
+    }
 }
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
index 0dbe788..5089a25 100644
--- a/keystore/java/android/security/KeyStoreHmacSpi.java
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -24,6 +24,7 @@
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
+import java.security.ProviderException;
 import java.security.spec.AlgorithmParameterSpec;
 
 import javax.crypto.MacSpi;
@@ -185,10 +186,10 @@
         }
 
         if (mOperationToken == null) {
-            throw new IllegalStateException("Keystore returned null operation token");
+            throw new ProviderException("Keystore returned null operation token");
         }
         if (mOperationHandle == 0) {
-            throw new IllegalStateException("Keystore returned invalid operation handle");
+            throw new ProviderException("Keystore returned invalid operation handle");
         }
 
         mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
@@ -206,17 +207,17 @@
         try {
             ensureKeystoreOperationInitialized();
         } catch (InvalidKeyException e) {
-            throw new IllegalStateException("Failed to reinitialize MAC", e);
+            throw new ProviderException("Failed to reinitialize MAC", e);
         }
 
         byte[] output;
         try {
             output = mChunkedStreamer.update(input, offset, len);
         } catch (KeyStoreException e) {
-            throw new IllegalStateException("Keystore operation failed", e);
+            throw new ProviderException("Keystore operation failed", e);
         }
         if ((output != null) && (output.length != 0)) {
-            throw new IllegalStateException("Update operation unexpectedly produced output");
+            throw new ProviderException("Update operation unexpectedly produced output");
         }
     }
 
@@ -225,14 +226,14 @@
         try {
             ensureKeystoreOperationInitialized();
         } catch (InvalidKeyException e) {
-            throw new IllegalStateException("Failed to reinitialize MAC", e);
+            throw new ProviderException("Failed to reinitialize MAC", e);
         }
 
         byte[] result;
         try {
             result = mChunkedStreamer.doFinal(null, 0, 0);
         } catch (KeyStoreException e) {
-            throw new IllegalStateException("Keystore operation failed", e);
+            throw new ProviderException("Keystore operation failed", e);
         }
 
         resetWhilePreservingInitState();
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index 68b5751..4b914c2 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -21,6 +21,7 @@
 import android.security.keymaster.KeymasterDefs;
 
 import java.security.InvalidAlgorithmParameterException;
+import java.security.ProviderException;
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
 import java.util.Date;
@@ -39,6 +40,17 @@
         public AES() {
             super(KeymasterDefs.KM_ALGORITHM_AES, 128);
         }
+
+        @Override
+        protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
+                throws InvalidAlgorithmParameterException {
+            super.engineInit(params, random);
+            if ((mKeySizeBits != 128) && (mKeySizeBits != 192) && (mKeySizeBits != 256)) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported key size: " + mKeySizeBits
+                        + ". Supported: 128, 192, 256.");
+            }
+        }
     }
 
     protected static abstract class HmacBase extends KeyStoreKeyGeneratorSpi {
@@ -87,6 +99,11 @@
     private KeyGeneratorSpec mSpec;
     private SecureRandom mRng;
 
+    protected int mKeySizeBits;
+    private int[] mKeymasterPurposes;
+    private int[] mKeymasterBlockModes;
+    private int[] mKeymasterPaddings;
+
     protected KeyStoreKeyGeneratorSpi(
             int keymasterAlgorithm,
             int defaultKeySizeBits) {
@@ -100,6 +117,97 @@
         mKeymasterAlgorithm = keymasterAlgorithm;
         mKeymasterDigest = keymasterDigest;
         mDefaultKeySizeBits = defaultKeySizeBits;
+        if (mDefaultKeySizeBits <= 0) {
+            throw new IllegalArgumentException("Default key size must be positive");
+        }
+
+        if ((mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) && (mKeymasterDigest == -1)) {
+            throw new IllegalArgumentException(
+                    "Digest algorithm must be specified for HMAC key");
+        }
+    }
+
+    @Override
+    protected void engineInit(SecureRandom random) {
+        throw new UnsupportedOperationException("Cannot initialize without an "
+                + KeyGeneratorSpec.class.getName() + " parameter");
+    }
+
+    @Override
+    protected void engineInit(int keySize, SecureRandom random) {
+        throw new UnsupportedOperationException("Cannot initialize without a "
+                + KeyGeneratorSpec.class.getName() + " parameter");
+    }
+
+    @Override
+    protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        resetAll();
+
+        boolean success = false;
+        try {
+            if ((params == null) || (!(params instanceof KeyGeneratorSpec))) {
+                throw new InvalidAlgorithmParameterException("Cannot initialize without an "
+                        + KeyGeneratorSpec.class.getName() + " parameter");
+            }
+            KeyGeneratorSpec spec = (KeyGeneratorSpec) params;
+            if (spec.getKeystoreAlias() == null) {
+                throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
+            }
+
+            mRng = random;
+            mSpec = spec;
+
+            mKeySizeBits = (spec.getKeySize() != -1) ? spec.getKeySize() : mDefaultKeySizeBits;
+            if (mKeySizeBits <= 0) {
+                throw new InvalidAlgorithmParameterException(
+                        "Key size must be positive: " + mKeySizeBits);
+            } else if ((mKeySizeBits % 8) != 0) {
+                throw new InvalidAlgorithmParameterException(
+                        "Key size in must be a multiple of 8: " + mKeySizeBits);
+            }
+
+            try {
+                mKeymasterPurposes =
+                        KeyStoreKeyProperties.Purpose.allToKeymaster(spec.getPurposes());
+                mKeymasterPaddings = KeyStoreKeyProperties.EncryptionPadding.allToKeymaster(
+                        spec.getEncryptionPaddings());
+                mKeymasterBlockModes =
+                        KeyStoreKeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
+                if (((spec.getPurposes() & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
+                        && (spec.isRandomizedEncryptionRequired())) {
+                    for (int keymasterBlockMode : mKeymasterBlockModes) {
+                        if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatible(
+                                keymasterBlockMode)) {
+                            throw new InvalidAlgorithmParameterException(
+                                    "Randomized encryption (IND-CPA) required but may be violated"
+                                    + " by block mode: "
+                                    + KeyStoreKeyProperties.BlockMode.fromKeymaster(
+                                            keymasterBlockMode)
+                                    + ". See " + KeyGeneratorSpec.class.getName()
+                                    + " documentation.");
+                        }
+                    }
+                }
+            } catch (IllegalArgumentException e) {
+                throw new InvalidAlgorithmParameterException(e);
+            }
+
+            success = true;
+        } finally {
+            if (!success) {
+                resetAll();
+            }
+        }
+    }
+
+    private void resetAll() {
+        mSpec = null;
+        mRng = null;
+        mKeySizeBits = -1;
+        mKeymasterPurposes = null;
+        mKeymasterPaddings = null;
+        mKeymasterBlockModes = null;
     }
 
     @Override
@@ -117,43 +225,14 @@
         }
 
         KeymasterArguments args = new KeymasterArguments();
+        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
         args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
         if (mKeymasterDigest != -1) {
             args.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
         }
-        if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
-            if (mKeymasterDigest == -1) {
-                throw new IllegalStateException("Digest algorithm must be specified for HMAC key");
-            }
-        }
-        int keySizeBits = (spec.getKeySize() != -1) ? spec.getKeySize() : mDefaultKeySizeBits;
-        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keySizeBits);
-        @KeyStoreKeyProperties.PurposeEnum int purposes = spec.getPurposes();
-        int[] keymasterBlockModes = KeymasterUtils.getKeymasterBlockModesFromJcaBlockModes(
-                spec.getBlockModes());
-        if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0)
-                && (spec.isRandomizedEncryptionRequired())) {
-            for (int keymasterBlockMode : keymasterBlockModes) {
-                if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatible(keymasterBlockMode)) {
-                    throw new IllegalStateException(
-                            "Randomized encryption (IND-CPA) required but may be violated by block"
-                            + " mode: "
-                            + KeymasterUtils.getJcaBlockModeFromKeymasterBlockMode(
-                                    keymasterBlockMode)
-                            + ". See KeyGeneratorSpec documentation.");
-                }
-            }
-        }
-
-        for (int keymasterPurpose :
-            KeyStoreKeyProperties.Purpose.allToKeymaster(purposes)) {
-            args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose);
-        }
-        args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
-        args.addInts(
-                KeymasterDefs.KM_TAG_PADDING,
-                KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings(
-                        spec.getEncryptionPaddings()));
+        args.addInts(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
+        args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
+        args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
         KeymasterUtils.addUserAuthArgs(args,
                 spec.getContext(),
                 spec.isUserAuthenticationRequired(),
@@ -168,57 +247,31 @@
                 (spec.getKeyValidityForConsumptionEnd() != null)
                 ? spec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
 
-        if (((purposes & 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);
         }
 
-        byte[] additionalEntropy = null;
-        SecureRandom rng = mRng;
-        if (rng != null) {
-            additionalEntropy = new byte[(keySizeBits + 7) / 8];
-            rng.nextBytes(additionalEntropy);
-        }
-
+        byte[] additionalEntropy =
+                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
+                        mRng, (mKeySizeBits + 7) / 8);
         int flags = spec.getFlags();
         String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias();
+        KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
         int errorCode = mKeyStore.generateKey(
-                keyAliasInKeystore, args, additionalEntropy, flags, new KeyCharacteristics());
+                keyAliasInKeystore, args, additionalEntropy, flags, resultingKeyCharacteristics);
         if (errorCode != KeyStore.NO_ERROR) {
-            throw new IllegalStateException(
+            throw new ProviderException(
                     "Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
         }
-        String keyAlgorithmJCA =
-                KeymasterUtils.getJcaSecretKeyAlgorithm(mKeymasterAlgorithm, mKeymasterDigest);
+        String keyAlgorithmJCA;
+        try {
+            keyAlgorithmJCA = KeyStoreKeyProperties.Algorithm.fromKeymasterSecretKeyAlgorithm(
+                    mKeymasterAlgorithm, mKeymasterDigest);
+        } catch (IllegalArgumentException e) {
+            throw new ProviderException("Failed to obtain JCA secret key algorithm name", e);
+        }
         return new KeyStoreSecretKey(keyAliasInKeystore, keyAlgorithmJCA);
     }
-
-    @Override
-    protected void engineInit(SecureRandom random) {
-        throw new UnsupportedOperationException("Cannot initialize without an "
-                + KeyGeneratorSpec.class.getName() + " parameter");
-    }
-
-    @Override
-    protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
-            throws InvalidAlgorithmParameterException {
-        if ((params == null) || (!(params instanceof KeyGeneratorSpec))) {
-            throw new InvalidAlgorithmParameterException("Cannot initialize without an "
-                    + KeyGeneratorSpec.class.getName() + " parameter");
-        }
-        KeyGeneratorSpec spec = (KeyGeneratorSpec) params;
-        if (spec.getKeystoreAlias() == null) {
-            throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
-        }
-
-        mSpec = spec;
-        mRng = random;
-    }
-
-    @Override
-    protected void engineInit(int keySize, SecureRandom random) {
-        throw new UnsupportedOperationException("Cannot initialize without a "
-                + KeyGeneratorSpec.class.getName() + " parameter");
-    }
 }
diff --git a/keystore/java/android/security/KeyStoreKeyProperties.java b/keystore/java/android/security/KeyStoreKeyProperties.java
index b85ec53..1cf6a7a 100644
--- a/keystore/java/android/security/KeyStoreKeyProperties.java
+++ b/keystore/java/android/security/KeyStoreKeyProperties.java
@@ -17,13 +17,23 @@
 package android.security;
 
 import android.annotation.IntDef;
+import android.annotation.StringDef;
 import android.security.keymaster.KeymasterDefs;
 
 import libcore.util.EmptyArray;
 
 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.
@@ -37,7 +47,7 @@
     public @interface PurposeEnum {}
 
     /**
-     * Purpose of key.
+     * Purposes of key.
      */
     public static abstract class Purpose {
         private Purpose() {}
@@ -122,6 +132,514 @@
     }
 
     @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,
+        })
+    public @interface AlgorithmEnum {}
+
+    /**
+     * 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 RSA = "RSA";
+
+        /** Elliptic Curve (EC) key. */
+        public static final String EC = "EC";
+
+        /** 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 HMAC_SHA1 = "HmacSHA1";
+
+        /** 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 HMAC_SHA256 = "HmacSHA256";
+
+        /** 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 HMAC_SHA512 = "HmacSHA512";
+
+        /**
+         * @hide
+         */
+        static int toKeymasterSecretKeyAlgorithm(@AlgorithmEnum String algorithm) {
+            if (AES.equalsIgnoreCase(algorithm)) {
+                return KeymasterDefs.KM_ALGORITHM_AES;
+            } else if (algorithm.toUpperCase(Locale.US).startsWith("HMAC")) {
+                return KeymasterDefs.KM_ALGORITHM_HMAC;
+            } else {
+                throw new IllegalArgumentException(
+                        "Unsupported secret key algorithm: " + algorithm);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @AlgorithmEnum String fromKeymasterSecretKeyAlgorithm(
+                int keymasterAlgorithm, int keymasterDigest) {
+            switch (keymasterAlgorithm) {
+                case KeymasterDefs.KM_ALGORITHM_AES:
+                    if (keymasterDigest != -1) {
+                        throw new IllegalArgumentException("Digest not supported for AES key: "
+                                + Digest.fromKeymaster(keymasterDigest));
+                    }
+                    return AES;
+                case KeymasterDefs.KM_ALGORITHM_HMAC:
+                    switch (keymasterDigest) {
+                        case KeymasterDefs.KM_DIGEST_SHA1:
+                            return HMAC_SHA1;
+                        case KeymasterDefs.KM_DIGEST_SHA_2_224:
+                            return HMAC_SHA224;
+                        case KeymasterDefs.KM_DIGEST_SHA_2_256:
+                            return HMAC_SHA256;
+                        case KeymasterDefs.KM_DIGEST_SHA_2_384:
+                            return HMAC_SHA384;
+                        case KeymasterDefs.KM_DIGEST_SHA_2_512:
+                            return HMAC_SHA512;
+                        default:
+                            throw new IllegalArgumentException("Unsupported HMAC digest: "
+                                    + Digest.fromKeymaster(keymasterDigest));
+                    }
+                default:
+                    throw new IllegalArgumentException(
+                            "Unsupported algorithm: " + keymasterAlgorithm);
+            }
+        }
+
+        /**
+         * @hide
+         *
+         * @return keymaster digest or {@code -1} if the algorithm does not involve a digest.
+         */
+        static int toKeymasterDigest(@AlgorithmEnum String algorithm) {
+            String algorithmUpper = algorithm.toUpperCase(Locale.US);
+            if (algorithmUpper.startsWith("HMAC")) {
+                String digestUpper = algorithmUpper.substring("HMAC".length());
+                switch (digestUpper) {
+                    case "SHA1":
+                        return KeymasterDefs.KM_DIGEST_SHA1;
+                    case "SHA224":
+                        return KeymasterDefs.KM_DIGEST_SHA_2_224;
+                    case "SHA256":
+                        return KeymasterDefs.KM_DIGEST_SHA_2_256;
+                    case "SHA384":
+                        return KeymasterDefs.KM_DIGEST_SHA_2_384;
+                    case "SHA512":
+                        return KeymasterDefs.KM_DIGEST_SHA_2_512;
+                    default:
+                        throw new IllegalArgumentException(
+                                "Unsupported HMAC digest: " + digestUpper);
+                }
+            } else {
+                return -1;
+            }
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef({
+        BlockMode.ECB,
+        BlockMode.CBC,
+        BlockMode.CTR,
+        BlockMode.GCM,
+        })
+    public @interface BlockModeEnum {}
+
+    /**
+     * Block modes that can be used when encrypting/decrypting using a key.
+     */
+    public 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(@BlockModeEnum String blockMode) {
+            if (ECB.equalsIgnoreCase(blockMode)) {
+                return KeymasterDefs.KM_MODE_ECB;
+            } else if (CBC.equalsIgnoreCase(blockMode)) {
+                return KeymasterDefs.KM_MODE_CBC;
+            } else if (CTR.equalsIgnoreCase(blockMode)) {
+                return KeymasterDefs.KM_MODE_CTR;
+            } else if (GCM.equalsIgnoreCase(blockMode)) {
+                return KeymasterDefs.KM_MODE_GCM;
+            } else {
+                throw new IllegalArgumentException("Unsupported block mode: " + blockMode);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @BlockModeEnum String fromKeymaster(int blockMode) {
+            switch (blockMode) {
+                case KeymasterDefs.KM_MODE_ECB:
+                    return ECB;
+                case KeymasterDefs.KM_MODE_CBC:
+                    return CBC;
+                case KeymasterDefs.KM_MODE_CTR:
+                    return CTR;
+                case KeymasterDefs.KM_MODE_GCM:
+                    return GCM;
+                default:
+                    throw new IllegalArgumentException("Unsupported block mode: " + blockMode);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @BlockModeEnum String[] allFromKeymaster(Collection<Integer> blockModes) {
+            if ((blockModes == null) || (blockModes.isEmpty())) {
+                return EmptyArray.STRING;
+            }
+            @BlockModeEnum String[] result = new String[blockModes.size()];
+            int offset = 0;
+            for (int blockMode : blockModes) {
+                result[offset] = fromKeymaster(blockMode);
+                offset++;
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        static int[] allToKeymaster(@BlockModeEnum String[] blockModes) {
+            if ((blockModes == null) || (blockModes.length == 0)) {
+                return EmptyArray.INT;
+            }
+            int[] result = new int[blockModes.length];
+            for (int i = 0; i < blockModes.length; i++) {
+                result[i] = toKeymaster(blockModes[i]);
+            }
+            return result;
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef({
+        EncryptionPadding.NONE,
+        EncryptionPadding.PKCS7,
+        EncryptionPadding.RSA_PKCS1,
+        EncryptionPadding.RSA_OAEP,
+        })
+    public @interface EncryptionPaddingEnum {}
+
+    /**
+     * Padding schemes for encryption/decryption.
+     */
+    public 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(@EncryptionPaddingEnum String padding) {
+            if (NONE.equalsIgnoreCase(padding)) {
+                return KeymasterDefs.KM_PAD_NONE;
+            } else if (PKCS7.equalsIgnoreCase(padding)) {
+                return KeymasterDefs.KM_PAD_PKCS7;
+            } else if (RSA_PKCS1.equalsIgnoreCase(padding)) {
+                return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
+            } else if (RSA_OAEP.equalsIgnoreCase(padding)) {
+                return KeymasterDefs.KM_PAD_RSA_OAEP;
+            } else {
+                throw new IllegalArgumentException(
+                        "Unsupported encryption padding scheme: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @EncryptionPaddingEnum String fromKeymaster(int padding) {
+            switch (padding) {
+                case KeymasterDefs.KM_PAD_NONE:
+                    return NONE;
+                case KeymasterDefs.KM_PAD_PKCS7:
+                    return PKCS7;
+                case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
+                    return RSA_PKCS1;
+                case KeymasterDefs.KM_PAD_RSA_OAEP:
+                    return RSA_OAEP;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unsupported encryption padding: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static int[] allToKeymaster(@EncryptionPaddingEnum String[] paddings) {
+            if ((paddings == null) || (paddings.length == 0)) {
+                return EmptyArray.INT;
+            }
+            int[] result = new int[paddings.length];
+            for (int i = 0; i < paddings.length; i++) {
+                result[i] = toKeymaster(paddings[i]);
+            }
+            return result;
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef({
+        SignaturePadding.RSA_PKCS1,
+        SignaturePadding.RSA_PSS,
+        })
+    public @interface SignaturePaddingEnum {}
+
+    /**
+     * Padding schemes for signing/verification.
+     */
+    public 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(@SignaturePaddingEnum String padding) {
+            switch (padding.toUpperCase(Locale.US)) {
+                case RSA_PKCS1:
+                    return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN;
+                case RSA_PSS:
+                    return KeymasterDefs.KM_PAD_RSA_PSS;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unsupported signature padding scheme: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @SignaturePaddingEnum String fromKeymaster(int padding) {
+            switch (padding) {
+                case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN:
+                    return RSA_PKCS1;
+                case KeymasterDefs.KM_PAD_RSA_PSS:
+                    return RSA_PSS;
+                default:
+                    throw new IllegalArgumentException("Unsupported signature padding: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static int[] allToKeymaster(@SignaturePaddingEnum String[] paddings) {
+            if ((paddings == null) || (paddings.length == 0)) {
+                return EmptyArray.INT;
+            }
+            int[] result = new int[paddings.length];
+            for (int i = 0; i < paddings.length; i++) {
+                result[i] = toKeymaster(paddings[i]);
+            }
+            return result;
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef({
+        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).
+     */
+    public 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(@DigestEnum String digest) {
+            switch (digest.toUpperCase(Locale.US)) {
+                case SHA1:
+                    return KeymasterDefs.KM_DIGEST_SHA1;
+                case SHA224:
+                    return KeymasterDefs.KM_DIGEST_SHA_2_224;
+                case SHA256:
+                    return KeymasterDefs.KM_DIGEST_SHA_2_256;
+                case SHA384:
+                    return KeymasterDefs.KM_DIGEST_SHA_2_384;
+                case SHA512:
+                    return KeymasterDefs.KM_DIGEST_SHA_2_512;
+                case NONE:
+                    return KeymasterDefs.KM_DIGEST_NONE;
+                case MD5:
+                    return KeymasterDefs.KM_DIGEST_MD5;
+                default:
+                    throw new IllegalArgumentException("Unsupported digest algorithm: " + digest);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @DigestEnum String fromKeymaster(int digest) {
+            switch (digest) {
+                case KeymasterDefs.KM_DIGEST_NONE:
+                    return NONE;
+                case KeymasterDefs.KM_DIGEST_MD5:
+                    return MD5;
+                case KeymasterDefs.KM_DIGEST_SHA1:
+                    return SHA1;
+                case KeymasterDefs.KM_DIGEST_SHA_2_224:
+                    return SHA224;
+                case KeymasterDefs.KM_DIGEST_SHA_2_256:
+                    return SHA256;
+                case KeymasterDefs.KM_DIGEST_SHA_2_384:
+                    return SHA384;
+                case KeymasterDefs.KM_DIGEST_SHA_2_512:
+                    return SHA512;
+                default:
+                    throw new IllegalArgumentException("Unsupported digest algorithm: " + digest);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        static @DigestEnum String[] allFromKeymaster(Collection<Integer> digests) {
+            if (digests.isEmpty()) {
+                return EmptyArray.STRING;
+            }
+            String[] result = new String[digests.size()];
+            int offset = 0;
+            for (int digest : digests) {
+                result[offset] = fromKeymaster(digest);
+                offset++;
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        static int[] allToKeymaster(@DigestEnum String[] digests) {
+            if ((digests == null) || (digests.length == 0)) {
+                return EmptyArray.INT;
+            }
+            int[] result = new int[digests.length];
+            int offset = 0;
+            for (@DigestEnum String digest : digests) {
+                result[offset] = toKeymaster(digest);
+                offset++;
+            }
+            return result;
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef({Origin.GENERATED, Origin.IMPORTED, Origin.UNKNOWN})
     public @interface OriginEnum {}
 
@@ -138,7 +656,7 @@
         public static final int IMPORTED = 1 << 1;
 
         /**
-         * Origin of the key is unknown. This can occur only for keys backed by an old TEE
+         * 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;
diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java
index 96d58d8..a630a0a 100644
--- a/keystore/java/android/security/KeyStoreKeySpec.java
+++ b/keystore/java/android/security/KeyStoreKeySpec.java
@@ -26,40 +26,40 @@
 public class KeyStoreKeySpec implements KeySpec {
     private final String mKeystoreAlias;
     private final int mKeySize;
-    private final boolean mTeeBacked;
+    private final boolean mInsideSecureHardware;
     private final @KeyStoreKeyProperties.OriginEnum int mOrigin;
     private final Date mKeyValidityStart;
     private final Date mKeyValidityForOriginationEnd;
     private final Date mKeyValidityForConsumptionEnd;
     private final @KeyStoreKeyProperties.PurposeEnum int mPurposes;
-    private final String[] mEncryptionPaddings;
-    private final String[] mSignaturePaddings;
-    private final String[] mDigests;
-    private final String[] mBlockModes;
+    private final @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
+    private final @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
+    private final @KeyStoreKeyProperties.DigestEnum String[] mDigests;
+    private final @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
     private final boolean mUserAuthenticationRequired;
     private final int mUserAuthenticationValidityDurationSeconds;
-    private final boolean mUserAuthenticationRequirementTeeEnforced;
+    private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
 
     /**
      * @hide
      */
     KeyStoreKeySpec(String keystoreKeyAlias,
-            boolean teeBacked,
+            boolean insideSecureHardware,
             @KeyStoreKeyProperties.OriginEnum int origin,
             int keySize,
             Date keyValidityStart,
             Date keyValidityForOriginationEnd,
             Date keyValidityForConsumptionEnd,
             @KeyStoreKeyProperties.PurposeEnum int purposes,
-            String[] encryptionPaddings,
-            String[] signaturePaddings,
-            String[] digests,
-            String[] blockModes,
+            @KeyStoreKeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
+            @KeyStoreKeyProperties.SignaturePaddingEnum String[] signaturePaddings,
+            @KeyStoreKeyProperties.DigestEnum String[] digests,
+            @KeyStoreKeyProperties.BlockModeEnum String[] blockModes,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds,
-            boolean userAuthenticationRequirementTeeEnforced) {
+            boolean userAuthenticationRequirementEnforcedBySecureHardware) {
         mKeystoreAlias = keystoreKeyAlias;
-        mTeeBacked = teeBacked;
+        mInsideSecureHardware = insideSecureHardware;
         mOrigin = origin;
         mKeySize = keySize;
         mKeyValidityStart = keyValidityStart;
@@ -74,7 +74,8 @@
         mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
         mUserAuthenticationRequired = userAuthenticationRequired;
         mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
-        mUserAuthenticationRequirementTeeEnforced = userAuthenticationRequirementTeeEnforced;
+        mUserAuthenticationRequirementEnforcedBySecureHardware =
+                userAuthenticationRequirementEnforcedBySecureHardware;
     }
 
     /**
@@ -85,11 +86,12 @@
     }
 
     /**
-     * Returns {@code true} if the key is TEE-backed. Key material of TEE-backed keys is available
-     * in plaintext only inside the TEE.
+     * Returns {@code true} if the key resides inside secure hardware (e.g., Trusted Execution
+     * Environment (TEE) or Secure Element (SE)). Key material of such keys is available in
+     * plaintext only inside the secure hardware and is not exposed outside of it.
      */
-    public boolean isTeeBacked() {
-        return mTeeBacked;
+    public boolean isInsideSecureHardware() {
+        return mInsideSecureHardware;
     }
 
     /**
@@ -143,28 +145,28 @@
     /**
      * Gets the set of block modes with which the key can be used.
      */
-    public String[] getBlockModes() {
+    public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
         return ArrayUtils.cloneIfNotEmpty(mBlockModes);
     }
 
     /**
      * Gets the set of padding modes with which the key can be used when encrypting/decrypting.
      */
-    public String[] getEncryptionPaddings() {
+    public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
         return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings);
     }
 
     /**
      * Gets the set of padding modes with which the key can be used when signing/verifying.
      */
-    public String[] getSignaturePaddings() {
+    public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
         return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings);
     }
 
     /**
      * Gets the set of digest algorithms with which the key can be used.
      */
-    public String[] getDigests() {
+    public @KeyStoreKeyProperties.DigestEnum String[] getDigests() {
         return ArrayUtils.cloneIfNotEmpty(mDigests);
     }
 
@@ -179,10 +181,10 @@
 
     /**
      * Gets the duration of time (seconds) for which this key can be used after the user is
-     * successfully authenticated.
+     * successfully authenticated. This has effect only if user authentication is required.
      *
-     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
-     *         is required for every use of the key.
+     * @return duration in seconds or {@code -1} if authentication is required for every use of the
+     *         key.
      *
      * @see #isUserAuthenticationRequired()
      */
@@ -192,11 +194,12 @@
 
     /**
      * Returns {@code true} if the requirement that this key can only be used if the user has been
-     * authenticated if enforced by the TEE.
+     * authenticated if enforced by secure hardware (e.g., Trusted Execution Environment (TEE) or
+     * Secure Element (SE)).
      *
      * @see #isUserAuthenticationRequired()
      */
-    public boolean isUserAuthenticationRequirementTeeEnforced() {
-        return mUserAuthenticationRequirementTeeEnforced;
+    public boolean isUserAuthenticationRequirementEnforcedBySecureHardware() {
+        return mUserAuthenticationRequirementEnforcedBySecureHardware;
     }
 }
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index b4747e9..8d7a19f 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -45,10 +45,10 @@
     private final Date mKeyValidityForOriginationEnd;
     private final Date mKeyValidityForConsumptionEnd;
     private final @KeyStoreKeyProperties.PurposeEnum int mPurposes;
-    private final String[] mEncryptionPaddings;
-    private final String[] mSignaturePaddings;
-    private final String[] mDigests;
-    private final String[] mBlockModes;
+    private final @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
+    private final @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
+    private final @KeyStoreKeyProperties.DigestEnum String[] mDigests;
+    private final @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
     private final boolean mRandomizedEncryptionRequired;
     private final boolean mUserAuthenticationRequired;
     private final int mUserAuthenticationValidityDurationSeconds;
@@ -60,10 +60,10 @@
             Date keyValidityForOriginationEnd,
             Date keyValidityForConsumptionEnd,
             @KeyStoreKeyProperties.PurposeEnum int purposes,
-            String[] encryptionPaddings,
-            String[] signaturePaddings,
-            String[] digests,
-            String[] blockModes,
+            @KeyStoreKeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
+            @KeyStoreKeyProperties.SignaturePaddingEnum String[] signaturePaddings,
+            @KeyStoreKeyProperties.DigestEnum String[] digests,
+            @KeyStoreKeyProperties.BlockModeEnum String[] blockModes,
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
             int userAuthenticationValidityDurationSeconds) {
@@ -151,7 +151,7 @@
     /**
      * Gets the set of padding schemes with which the key can be used when encrypting/decrypting.
      */
-    public String[] getEncryptionPaddings() {
+    public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() {
         return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings);
     }
 
@@ -159,7 +159,7 @@
      * Gets the set of padding schemes with which the key can be used when signing or verifying
      * signatures.
      */
-    public String[] getSignaturePaddings() {
+    public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() {
         return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings);
     }
 
@@ -170,7 +170,7 @@
      *
      * @see #isDigestsSpecified()
      */
-    public String[] getDigests() {
+    public @KeyStoreKeyProperties.DigestEnum String[] getDigests() {
         if (mDigests == null) {
             throw new IllegalStateException("Digests not specified");
         }
@@ -190,7 +190,7 @@
     /**
      * Gets the set of block modes with which the key can be used.
      */
-    public String[] getBlockModes() {
+    public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() {
         return ArrayUtils.cloneIfNotEmpty(mBlockModes);
     }
 
@@ -218,10 +218,12 @@
 
     /**
      * Gets the duration of time (seconds) for which this key can be used after the user is
-     * successfully authenticated.
+     * successfully authenticated. This has effect only if user authentication is required.
      *
-     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
-     *         is required for every use of the key.
+     * @return duration in seconds or {@code -1} if authentication is required for every use of the
+     *         key.
+     *
+     * @see #isUserAuthenticationRequired()
      */
     public int getUserAuthenticationValidityDurationSeconds() {
         return mUserAuthenticationValidityDurationSeconds;
@@ -251,10 +253,10 @@
         private Date mKeyValidityForOriginationEnd;
         private Date mKeyValidityForConsumptionEnd;
         private @KeyStoreKeyProperties.PurposeEnum int mPurposes;
-        private String[] mEncryptionPaddings;
-        private String[] mSignaturePaddings;
-        private String[] mDigests;
-        private String[] mBlockModes;
+        private @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
+        private @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
+        private @KeyStoreKeyProperties.DigestEnum String[] mDigests;
+        private @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes;
         private boolean mRandomizedEncryptionRequired = true;
         private boolean mUserAuthenticationRequired;
         private int mUserAuthenticationValidityDurationSeconds = -1;
@@ -292,6 +294,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         *
          * @see #setKeyValidityEnd(Date)
          */
         public Builder setKeyValidityStart(Date startDate) {
@@ -304,6 +308,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         *
          * @see #setKeyValidityStart(Date)
          * @see #setKeyValidityForConsumptionEnd(Date)
          * @see #setKeyValidityForOriginationEnd(Date)
@@ -319,6 +325,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         *
          * @see #setKeyValidityForConsumptionEnd(Date)
          */
         public Builder setKeyValidityForOriginationEnd(Date endDate) {
@@ -332,6 +340,8 @@
          *
          * <p>By default, the key is valid at any instant.
          *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         *
          * @see #setKeyValidityForOriginationEnd(Date)
          */
         public Builder setKeyValidityForConsumptionEnd(Date endDate) {
@@ -343,6 +353,8 @@
          * Sets the set of purposes for which the key can be used.
          *
          * <p>This must be specified for all keys. There is no default.
+         *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
          */
         public Builder setPurposes(@KeyStoreKeyProperties.PurposeEnum int purposes) {
             mPurposes = purposes;
@@ -355,8 +367,11 @@
          * 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.
          */
-        public Builder setEncryptionPaddings(String... paddings) {
+        public Builder setEncryptionPaddings(
+                @KeyStoreKeyProperties.EncryptionPaddingEnum String... paddings) {
             mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings);
             return this;
         }
@@ -367,8 +382,11 @@
          * 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.
          */
-        public Builder setSignaturePaddings(String... paddings) {
+        public Builder setSignaturePaddings(
+                @KeyStoreKeyProperties.SignaturePaddingEnum String... paddings) {
             mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(paddings);
             return this;
         }
@@ -380,8 +398,10 @@
          *
          * <p>For HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()}. For
          * asymmetric signing keys this constraint must be specified.
+         *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
          */
-        public Builder setDigests(String... digests) {
+        public Builder setDigests(@KeyStoreKeyProperties.DigestEnum String... digests) {
             mDigests = ArrayUtils.cloneIfNotEmpty(digests);
             return this;
         }
@@ -391,8 +411,10 @@
          * 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.
          */
-        public Builder setBlockModes(String... blockModes) {
+        public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
             mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes);
             return this;
         }
@@ -430,6 +452,8 @@
          * <li>If you are using RSA encryption without padding, consider switching to padding
          * 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.
          */
         public Builder setRandomizedEncryptionRequired(boolean required) {
             mRandomizedEncryptionRequired = required;
@@ -449,6 +473,8 @@
          * <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
          * information</a>.
          *
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         *
          * @see #setUserAuthenticationValidityDurationSeconds(int)
          */
         public Builder setUserAuthenticationRequired(boolean required) {
@@ -462,7 +488,9 @@
          *
          * <p>By default, the user needs to authenticate for every use of the key.
          *
-         * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
+         * <p><b>NOTE: This has currently no effect on asymmetric key pairs.
+         *
+         * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
          *        every use of the key.
          *
          * @see #setUserAuthenticationRequired(boolean)
diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
index bfe09e3..548296b 100644
--- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
@@ -74,22 +74,22 @@
                     + " Keystore error: " + errorCode);
         }
 
-        boolean teeBacked;
+        boolean insideSecureHardware;
         @KeyStoreKeyProperties.OriginEnum int origin;
         int keySize;
         @KeyStoreKeyProperties.PurposeEnum int purposes;
         String[] encryptionPaddings;
-        String[] digests;
-        String[] blockModes;
+        @KeyStoreKeyProperties.DigestEnum String[] digests;
+        @KeyStoreKeyProperties.BlockModeEnum String[] blockModes;
         int keymasterSwEnforcedUserAuthenticators;
         int keymasterHwEnforcedUserAuthenticators;
         try {
             if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
-                teeBacked = true;
+                insideSecureHardware = true;
                 origin = KeyStoreKeyProperties.Origin.fromKeymaster(
                         keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_ORIGIN, -1));
             } else if (keyCharacteristics.swEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
-                teeBacked = false;
+                insideSecureHardware = false;
                 origin = KeyStoreKeyProperties.Origin.fromKeymaster(
                         keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_ORIGIN, -1));
             } else {
@@ -105,10 +105,10 @@
 
             List<String> encryptionPaddingsList = new ArrayList<String>();
             for (int keymasterPadding : keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PADDING)) {
-                String jcaPadding;
+                @KeyStoreKeyProperties.EncryptionPaddingEnum String jcaPadding;
                 try {
-                    jcaPadding = KeymasterUtils.getJcaEncryptionPaddingFromKeymasterPadding(
-                            keymasterPadding);
+                    jcaPadding =
+                            KeyStoreKeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding);
                 } catch (IllegalArgumentException e) {
                     throw new InvalidKeySpecException(
                             "Unsupported encryption padding: " + keymasterPadding);
@@ -118,9 +118,9 @@
             encryptionPaddings =
                     encryptionPaddingsList.toArray(new String[encryptionPaddingsList.size()]);
 
-            digests = KeymasterUtils.getJcaDigestAlgorithmsFromKeymasterDigests(
+            digests = KeyStoreKeyProperties.Digest.allFromKeymaster(
                     keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST));
-            blockModes = KeymasterUtils.getJcaBlockModesFromKeymasterBlockModes(
+            blockModes = KeyStoreKeyProperties.BlockMode.allFromKeymaster(
                     keyCharacteristics.getInts(KeymasterDefs.KM_TAG_BLOCK_MODE));
             keymasterSwEnforcedUserAuthenticators =
                     keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
@@ -150,12 +150,12 @@
                 !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
         int userAuthenticationValidityDurationSeconds =
                 keyCharacteristics.getInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1);
-        boolean userAuthenticationRequirementEnforcedInTee = (userAuthenticationRequired)
+        boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
                 && (keymasterHwEnforcedUserAuthenticators != 0)
                 && (keymasterSwEnforcedUserAuthenticators == 0);
 
         return new KeyStoreKeySpec(entryAlias,
-                teeBacked,
+                insideSecureHardware,
                 origin,
                 keySize,
                 keyValidityStart,
@@ -168,7 +168,7 @@
                 blockModes,
                 userAuthenticationRequired,
                 userAuthenticationValidityDurationSeconds,
-                userAuthenticationRequirementEnforcedInTee);
+                userAuthenticationRequirementEnforcedBySecureHardware);
     }
 
     @Override
diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java
index aa44ecd..df67ae7 100644
--- a/keystore/java/android/security/KeymasterUtils.java
+++ b/keystore/java/android/security/KeymasterUtils.java
@@ -21,11 +21,6 @@
 import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterDefs;
 
-import libcore.util.EmptyArray;
-
-import java.util.Collection;
-import java.util.Locale;
-
 /**
  * @hide
  */
@@ -33,152 +28,6 @@
 
     private KeymasterUtils() {}
 
-    public static int getKeymasterAlgorithmFromJcaSecretKeyAlgorithm(String jcaKeyAlgorithm) {
-        if ("AES".equalsIgnoreCase(jcaKeyAlgorithm)) {
-            return KeymasterDefs.KM_ALGORITHM_AES;
-        } else if (jcaKeyAlgorithm.toUpperCase(Locale.US).startsWith("HMAC")) {
-            return KeymasterDefs.KM_ALGORITHM_HMAC;
-        } else {
-            throw new IllegalArgumentException(
-                    "Unsupported secret key algorithm: " + jcaKeyAlgorithm);
-        }
-    }
-
-    public static String getJcaSecretKeyAlgorithm(int keymasterAlgorithm, int keymasterDigest) {
-        switch (keymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_AES:
-                if (keymasterDigest != -1) {
-                    throw new IllegalArgumentException(
-                            "Digest not supported for AES key: " + keymasterDigest);
-                }
-                return "AES";
-            case KeymasterDefs.KM_ALGORITHM_HMAC:
-                switch (keymasterDigest) {
-                    case KeymasterDefs.KM_DIGEST_SHA1:
-                        return "HmacSHA1";
-                    case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                        return "HmacSHA224";
-                    case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                        return "HmacSHA256";
-                    case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                        return "HmacSHA384";
-                    case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                        return "HmacSHA512";
-                    default:
-                        throw new IllegalArgumentException(
-                                "Unsupported HMAC digest: " + keymasterDigest);
-                }
-            default:
-                throw new IllegalArgumentException("Unsupported algorithm: " + keymasterAlgorithm);
-        }
-    }
-
-    public static String getJcaKeyPairAlgorithmFromKeymasterAlgorithm(int keymasterAlgorithm) {
-        switch (keymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-                return "RSA";
-            case KeymasterDefs.KM_ALGORITHM_EC:
-                return "EC";
-            default:
-                throw new IllegalArgumentException("Unsupported algorithm: " + keymasterAlgorithm);
-        }
-    }
-
-    public static int getKeymasterDigestfromJcaSecretKeyAlgorithm(String jcaKeyAlgorithm) {
-        String algorithmUpper = jcaKeyAlgorithm.toUpperCase(Locale.US);
-        if (algorithmUpper.startsWith("HMAC")) {
-            String digestUpper = algorithmUpper.substring("HMAC".length());
-            switch (digestUpper) {
-                case "MD5":
-                    return KeymasterDefs.KM_DIGEST_MD5;
-                case "SHA1":
-                    return KeymasterDefs.KM_DIGEST_SHA1;
-                case "SHA224":
-                    return KeymasterDefs.KM_DIGEST_SHA_2_224;
-                case "SHA256":
-                    return KeymasterDefs.KM_DIGEST_SHA_2_256;
-                case "SHA384":
-                    return KeymasterDefs.KM_DIGEST_SHA_2_384;
-                case "SHA512":
-                    return KeymasterDefs.KM_DIGEST_SHA_2_512;
-                default:
-                    throw new IllegalArgumentException("Unsupported HMAC digest: " + digestUpper);
-            }
-        } else {
-            return -1;
-        }
-    }
-
-    public static int getKeymasterDigestFromJcaDigestAlgorithm(String jcaDigestAlgorithm) {
-        if (jcaDigestAlgorithm.equalsIgnoreCase("SHA-1")) {
-            return KeymasterDefs.KM_DIGEST_SHA1;
-        } else if (jcaDigestAlgorithm.equalsIgnoreCase("SHA-224")) {
-            return KeymasterDefs.KM_DIGEST_SHA_2_224;
-        } else if (jcaDigestAlgorithm.equalsIgnoreCase("SHA-256")) {
-            return KeymasterDefs.KM_DIGEST_SHA_2_256;
-        } else if (jcaDigestAlgorithm.equalsIgnoreCase("SHA-384")) {
-            return KeymasterDefs.KM_DIGEST_SHA_2_384;
-        } else if (jcaDigestAlgorithm.equalsIgnoreCase("SHA-512")) {
-            return KeymasterDefs.KM_DIGEST_SHA_2_512;
-        } else if (jcaDigestAlgorithm.equalsIgnoreCase("NONE")) {
-            return KeymasterDefs.KM_DIGEST_NONE;
-        } else if (jcaDigestAlgorithm.equalsIgnoreCase("MD5")) {
-            return KeymasterDefs.KM_DIGEST_MD5;
-        } else {
-            throw new IllegalArgumentException(
-                    "Unsupported digest algorithm: " + jcaDigestAlgorithm);
-        }
-    }
-
-    public static String getJcaDigestAlgorithmFromKeymasterDigest(int keymasterDigest) {
-        switch (keymasterDigest) {
-            case KeymasterDefs.KM_DIGEST_NONE:
-                return "NONE";
-            case KeymasterDefs.KM_DIGEST_MD5:
-                return "MD5";
-            case KeymasterDefs.KM_DIGEST_SHA1:
-                return "SHA-1";
-            case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                return "SHA-224";
-            case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                return "SHA-256";
-            case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                return "SHA-384";
-            case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                return "SHA-512";
-            default:
-                throw new IllegalArgumentException(
-                        "Unsupported digest algorithm: " + keymasterDigest);
-        }
-    }
-
-    public static String[] getJcaDigestAlgorithmsFromKeymasterDigests(
-            Collection<Integer> keymasterDigests) {
-        if (keymasterDigests.isEmpty()) {
-            return EmptyArray.STRING;
-        }
-        String[] result = new String[keymasterDigests.size()];
-        int offset = 0;
-        for (int keymasterDigest : keymasterDigests) {
-            result[offset] = getJcaDigestAlgorithmFromKeymasterDigest(keymasterDigest);
-            offset++;
-        }
-        return result;
-    }
-
-    public static int[] getKeymasterDigestsFromJcaDigestAlgorithms(String[] jcaDigestAlgorithms) {
-        if ((jcaDigestAlgorithms == null) || (jcaDigestAlgorithms.length == 0)) {
-            return EmptyArray.INT;
-        }
-        int[] result = new int[jcaDigestAlgorithms.length];
-        int offset = 0;
-        for (String jcaDigestAlgorithm : jcaDigestAlgorithms) {
-            result[offset] = getKeymasterDigestFromJcaDigestAlgorithm(jcaDigestAlgorithm);
-            offset++;
-        }
-        return result;
-    }
-
     public static int getDigestOutputSizeBits(int keymasterDigest) {
         switch (keymasterDigest) {
             case KeymasterDefs.KM_DIGEST_NONE:
@@ -200,60 +49,6 @@
         }
     }
 
-    public static int getKeymasterBlockModeFromJcaBlockMode(String jcaBlockMode) {
-        if ("ECB".equalsIgnoreCase(jcaBlockMode)) {
-            return KeymasterDefs.KM_MODE_ECB;
-        } else if ("CBC".equalsIgnoreCase(jcaBlockMode)) {
-            return KeymasterDefs.KM_MODE_CBC;
-        } else if ("CTR".equalsIgnoreCase(jcaBlockMode)) {
-            return KeymasterDefs.KM_MODE_CTR;
-        } else if ("GCM".equalsIgnoreCase(jcaBlockMode)) {
-            return KeymasterDefs.KM_MODE_GCM;
-        } else {
-            throw new IllegalArgumentException("Unsupported block mode: " + jcaBlockMode);
-        }
-    }
-
-    public static String getJcaBlockModeFromKeymasterBlockMode(int keymasterBlockMode) {
-        switch (keymasterBlockMode) {
-            case KeymasterDefs.KM_MODE_ECB:
-                return "ECB";
-            case KeymasterDefs.KM_MODE_CBC:
-                return "CBC";
-            case KeymasterDefs.KM_MODE_CTR:
-                return "CTR";
-            case KeymasterDefs.KM_MODE_GCM:
-                return "GCM";
-            default:
-                throw new IllegalArgumentException("Unsupported block mode: " + keymasterBlockMode);
-        }
-    }
-
-    public static String[] getJcaBlockModesFromKeymasterBlockModes(
-            Collection<Integer> keymasterBlockModes) {
-        if ((keymasterBlockModes == null) || (keymasterBlockModes.isEmpty())) {
-            return EmptyArray.STRING;
-        }
-        String[] result = new String[keymasterBlockModes.size()];
-        int offset = 0;
-        for (int keymasterBlockMode : keymasterBlockModes) {
-            result[offset] = getJcaBlockModeFromKeymasterBlockMode(keymasterBlockMode);
-            offset++;
-        }
-        return result;
-    }
-
-    public static int[] getKeymasterBlockModesFromJcaBlockModes(String[] jcaBlockModes) {
-        if ((jcaBlockModes == null) || (jcaBlockModes.length == 0)) {
-            return EmptyArray.INT;
-        }
-        int[] result = new int[jcaBlockModes.length];
-        for (int i = 0; i < jcaBlockModes.length; i++) {
-            result[i] = getKeymasterBlockModeFromJcaBlockMode(jcaBlockModes[i]);
-        }
-        return result;
-    }
-
     public static boolean isKeymasterBlockModeIndCpaCompatible(int keymasterBlockMode) {
         switch (keymasterBlockMode) {
             case KeymasterDefs.KM_MODE_ECB:
@@ -267,82 +62,6 @@
         }
     }
 
-    public static int getKeymasterPaddingFromJcaEncryptionPadding(String jcaPadding) {
-        if ("NoPadding".equalsIgnoreCase(jcaPadding)) {
-            return KeymasterDefs.KM_PAD_NONE;
-        } else if ("PKCS7Padding".equalsIgnoreCase(jcaPadding)) {
-            return KeymasterDefs.KM_PAD_PKCS7;
-        } else if ("PKCS1Padding".equalsIgnoreCase(jcaPadding)) {
-            return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
-        } else if ("OEAPPadding".equalsIgnoreCase(jcaPadding)) {
-            return KeymasterDefs.KM_PAD_RSA_OAEP;
-        } else {
-            throw new IllegalArgumentException(
-                    "Unsupported encryption padding scheme: " + jcaPadding);
-        }
-    }
-
-    public static String getJcaEncryptionPaddingFromKeymasterPadding(int keymasterPadding) {
-        switch (keymasterPadding) {
-            case KeymasterDefs.KM_PAD_NONE:
-                return "NoPadding";
-            case KeymasterDefs.KM_PAD_PKCS7:
-                return "PKCS7Padding";
-            case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
-                return "PKCS1Padding";
-            case KeymasterDefs.KM_PAD_RSA_OAEP:
-                return "OEAPPadding";
-            default:
-                throw new IllegalArgumentException(
-                        "Unsupported encryption padding: " + keymasterPadding);
-        }
-    }
-
-    public static int getKeymasterPaddingFromJcaSignaturePadding(String jcaPadding) {
-        if ("PKCS#1".equalsIgnoreCase(jcaPadding)) {
-            return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN;
-        } if ("PSS".equalsIgnoreCase(jcaPadding)) {
-            return KeymasterDefs.KM_PAD_RSA_PSS;
-        } else {
-            throw new IllegalArgumentException(
-                    "Unsupported signature padding scheme: " + jcaPadding);
-        }
-    }
-
-    public static String getJcaSignaturePaddingFromKeymasterPadding(int keymasterPadding) {
-        switch (keymasterPadding) {
-            case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN:
-                return "PKCS#1";
-            case KeymasterDefs.KM_PAD_RSA_PSS:
-                return "PSS";
-            default:
-                throw new IllegalArgumentException(
-                        "Unsupported signature padding: " + keymasterPadding);
-        }
-    }
-
-    public static int[] getKeymasterPaddingsFromJcaEncryptionPaddings(String[] jcaPaddings) {
-        if ((jcaPaddings == null) || (jcaPaddings.length == 0)) {
-            return EmptyArray.INT;
-        }
-        int[] result = new int[jcaPaddings.length];
-        for (int i = 0; i < jcaPaddings.length; i++) {
-            result[i] = getKeymasterPaddingFromJcaEncryptionPadding(jcaPaddings[i]);
-        }
-        return result;
-    }
-
-    public static int[] getKeymasterPaddingsFromJcaSignaturePaddings(String[] jcaPaddings) {
-        if ((jcaPaddings == null) || (jcaPaddings.length == 0)) {
-            return EmptyArray.INT;
-        }
-        int[] result = new int[jcaPaddings.length];
-        for (int i = 0; i < jcaPaddings.length; i++) {
-            result[i] = getKeymasterPaddingFromJcaSignaturePadding(jcaPaddings[i]);
-        }
-        return result;
-    }
-
     /**
      * Adds keymaster arguments to express the key's authorization policy supported by user
      * authentication.
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 19a5beb..2ae7b08 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3336,6 +3336,30 @@
     return NO_ERROR;
 }
 
+status_t ResTable::Theme::clear()
+{
+    if (kDebugTableTheme) {
+        ALOGI("Clearing theme %p...\n", this);
+        dumpToLog();
+    }
+
+    for (size_t i = 0; i < Res_MAXPACKAGE; i++) {
+        if (mPackages[i] != NULL) {
+            free_package(mPackages[i]);
+            mPackages[i] = NULL;
+        }
+    }
+
+    mTypeSpecFlags = 0;
+
+    if (kDebugTableTheme) {
+        ALOGI("Final theme:");
+        dumpToLog();
+    }
+
+    return NO_ERROR;
+}
+
 ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue,
         uint32_t* outTypeSpecFlags) const
 {
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index 882826e..2889d2f 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -112,9 +112,6 @@
     Texture* const mDelegate;
 }; // struct DelegateTexture
 
-/**
- * TODO: This method does not take the rotation flag into account
- */
 void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
     const float width = float(mTexture->width);
     const float height = float(mTexture->height);
@@ -128,7 +125,6 @@
         // pointers on 64 bit architectures.
         const int x = static_cast<int>(map[i++]);
         const int y = static_cast<int>(map[i++]);
-        bool rotated = map[i++] > 0;
 
         // Bitmaps should never be null, we're just extra paranoid
         if (!pixelRef) continue;
@@ -142,7 +138,7 @@
         texture->width = pixelRef->info().width();
         texture->height = pixelRef->info().height();
 
-        Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this);
+        Entry* entry = new Entry(pixelRef, texture, mapper, *this);
         texture->uvMapper = &entry->uvMapper;
 
         mEntries.add(entry->pixelRef, entry);
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 17c5281..f1cd0b4 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -45,8 +45,8 @@
 class AssetAtlas {
 public:
     /**
-     * Entry representing the position and rotation of a
-     * bitmap inside the atlas.
+     * Entry representing the texture and uvMapper of a PixelRef in the
+     * atlas
      */
     class Entry {
     public:
@@ -78,30 +78,15 @@
         SkPixelRef* pixelRef;
 
         /**
-         * Location of the bitmap inside the atlas, in pixels.
-         */
-        int x;
-        int y;
-
-        /**
-         * If set, the bitmap is rotated 90 degrees (clockwise)
-         * inside the atlas.
-         */
-        bool rotated;
-
-        /**
          * Atlas this entry belongs to.
          */
         const AssetAtlas& atlas;
 
-        Entry(SkPixelRef* pixelRef, int x, int y, bool rotated,
-                    Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas)
+        Entry(SkPixelRef* pixelRef, Texture* texture, const UvMapper& mapper,
+                    const AssetAtlas& atlas)
                 : texture(texture)
                 , uvMapper(mapper)
                 , pixelRef(pixelRef)
-                , x(x)
-                , y(y)
-                , rotated(rotated)
                 , atlas(atlas) {
         }
 
@@ -120,8 +105,7 @@
      * Initializes the atlas with the specified buffer and
      * map. The buffer is a gralloc'd texture that will be
      * used as an EGLImage. The map is a list of SkBitmap*
-     * and their (x, y) positions as well as their rotation
-     * flags.
+     * and their (x, y) positions
      *
      * This method returns immediately if the atlas is already
      * initialized. To re-initialize the atlas, you must
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 4540bec..e679bff 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -41,10 +41,6 @@
     ResourceCache& resourceCache = ResourceCache::getInstance();
     resourceCache.lock();
 
-    for (size_t i = 0; i < bitmapResources.size(); i++) {
-        resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
-    }
-
     for (size_t i = 0; i < patchResources.size(); i++) {
         resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
     }
@@ -59,7 +55,6 @@
         delete path;
     }
 
-    bitmapResources.clear();
     patchResources.clear();
     pathResources.clear();
     paints.clear();
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index 0064236..d997ef4 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -350,9 +350,10 @@
         // correctly, such as creating the bitmap from scratch, drawing with it, changing its
         // contents, and drawing again. The only fix would be to always copy it the first time,
         // which doesn't seem worth the extra cycles for this unlikely case.
-        const SkBitmap* cachedBitmap = mResourceCache.insert(bitmap);
-        mDisplayListData->bitmapResources.add(cachedBitmap);
-        return cachedBitmap;
+        SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
+        alloc().autoDestroy(localBitmap);
+        mDisplayListData->bitmapResources.push_back(localBitmap);
+        return localBitmap;
     }
 
     inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index fd32b6f..723a177 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -28,6 +28,8 @@
 bool Properties::debugLayersUpdates = false;
 bool Properties::debugOverdraw = false;
 bool Properties::showDirtyRegions = false;
+bool Properties::skipEmptyFrames = true;
+bool Properties::swapBuffersWithDamage = false;
 
 DebugLevel Properties::debugLevel = kDebugDisabled;
 OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default;
@@ -101,6 +103,9 @@
         debugLevel = (DebugLevel) atoi(property);
     }
 
+    skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true);
+    swapBuffersWithDamage = property_get_bool(PROPERTY_SWAP_WITH_DAMAGE, false);
+
     return (prevDebugLayersUpdates != debugLayersUpdates)
             || (prevDebugOverdraw != debugOverdraw)
             || (prevDebugStencilClip != debugStencilClip);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 46fa940..cb5560f 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -158,6 +158,21 @@
  */
 #define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder"
 
+/**
+ * Setting this property will enable or disable the dropping of frames with
+ * empty damage. Default is "true".
+ */
+#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage"
+
+/**
+ * Setting this property will enable usage of EGL_KHR_swap_buffers_with_damage
+ * See: https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt
+ * Default is "false" temporarily
+ * TODO: Change to "true", make sure to remove the log in EglManager::swapBuffers
+ * before changing this to default to true!
+ */
+#define PROPERTY_SWAP_WITH_DAMAGE "debug.hwui.swap_with_damage"
+
 ///////////////////////////////////////////////////////////////////////////////
 // Runtime configuration properties
 ///////////////////////////////////////////////////////////////////////////////
@@ -288,6 +303,10 @@
     static bool debugLayersUpdates;
     static bool debugOverdraw;
     static bool showDirtyRegions;
+    // TODO: Remove after stabilization period
+    static bool skipEmptyFrames;
+    // TODO: Remove after stabilization period
+    static bool swapBuffersWithDamage;
 
     static DebugLevel debugLevel;
     static OverdrawColorSet overdrawColorSet;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 454fedc..75d8134 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -59,21 +59,6 @@
     mLock.unlock();
 }
 
-const SkBitmap* ResourceCache::insert(const SkBitmap& bitmapResource) {
-    Mutex::Autolock _l(mLock);
-
-    BitmapKey bitmapKey(bitmapResource);
-    ssize_t index = mBitmapCache.indexOfKey(bitmapKey);
-    if (index == NAME_NOT_FOUND) {
-        SkBitmap* cachedBitmap = new SkBitmap(bitmapResource);
-        index = mBitmapCache.add(bitmapKey, cachedBitmap);
-        return cachedBitmap;
-    }
-
-    mBitmapCache.keyAt(index).mRefCount++;
-    return mBitmapCache.valueAt(index);
-}
-
 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
     Mutex::Autolock _l(mLock);
     incrementRefcountLocked(resource, resourceType);
@@ -98,11 +83,6 @@
     decrementRefcountLocked(resource);
 }
 
-void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) {
-    Mutex::Autolock _l(mLock);
-    decrementRefcountLocked(bitmapResource);
-}
-
 void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
     decrementRefcount((void*) patchResource);
 }
@@ -120,23 +100,6 @@
     }
 }
 
-void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) {
-    BitmapKey bitmapKey(*bitmapResource);
-    ssize_t index = mBitmapCache.indexOfKey(bitmapKey);
-
-    LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND,
-                    "Decrementing the reference of an untracked Bitmap");
-
-    const BitmapKey& cacheEntry = mBitmapCache.keyAt(index);
-    if (cacheEntry.mRefCount == 1) {
-        // delete the bitmap and remove it from the cache
-        delete mBitmapCache.valueAt(index);
-        mBitmapCache.removeItemsAt(index);
-    } else {
-        cacheEntry.mRefCount--;
-    }
-}
-
 void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
     decrementRefcountLocked((void*) patchResource);
 }
@@ -190,38 +153,5 @@
     delete ref;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Bitmap Key
-///////////////////////////////////////////////////////////////////////////////
-
-void BitmapKey::operator=(const BitmapKey& other) {
-    this->mRefCount = other.mRefCount;
-    this->mBitmapDimensions = other.mBitmapDimensions;
-    this->mPixelRefOrigin = other.mPixelRefOrigin;
-    this->mPixelRefStableID = other.mPixelRefStableID;
-}
-
-bool BitmapKey::operator==(const BitmapKey& other) const {
-    return mPixelRefStableID == other.mPixelRefStableID &&
-           mPixelRefOrigin == other.mPixelRefOrigin &&
-           mBitmapDimensions == other.mBitmapDimensions;
-}
-
-bool BitmapKey::operator<(const BitmapKey& other) const {
-    if (mPixelRefStableID != other.mPixelRefStableID) {
-        return mPixelRefStableID < other.mPixelRefStableID;
-    }
-    if (mPixelRefOrigin.x() != other.mPixelRefOrigin.x()) {
-        return mPixelRefOrigin.x() < other.mPixelRefOrigin.x();
-    }
-    if (mPixelRefOrigin.y() != other.mPixelRefOrigin.y()) {
-        return mPixelRefOrigin.y() < other.mPixelRefOrigin.y();
-    }
-    if (mBitmapDimensions.width() != other.mBitmapDimensions.width()) {
-        return mBitmapDimensions.width() < other.mBitmapDimensions.width();
-    }
-    return mBitmapDimensions.height() < other.mBitmapDimensions.height();
-}
-
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 6c483fa..4583c8d 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -51,37 +51,6 @@
     ResourceType resourceType;
 };
 
-class BitmapKey {
-public:
-    BitmapKey(const SkBitmap& bitmap)
-        : mRefCount(1)
-        , mBitmapDimensions(bitmap.dimensions())
-        , mPixelRefOrigin(bitmap.pixelRefOrigin())
-        , mPixelRefStableID(bitmap.pixelRef()->getStableID()) { }
-
-    void operator=(const BitmapKey& other);
-    bool operator==(const BitmapKey& other) const;
-    bool operator<(const BitmapKey& other) const;
-
-private:
-    // This constructor is only used by the KeyedVector implementation
-    BitmapKey()
-        : mRefCount(-1)
-        , mBitmapDimensions(SkISize::Make(0,0))
-        , mPixelRefOrigin(SkIPoint::Make(0,0))
-        , mPixelRefStableID(0) { }
-
-    // reference count of all HWUI object using this bitmap
-    mutable int mRefCount;
-
-    SkISize mBitmapDimensions;
-    SkIPoint mPixelRefOrigin;
-    uint32_t mPixelRefStableID;
-
-    friend class ResourceCache;
-    friend struct android::key_value_pair_t<BitmapKey, SkBitmap*>;
-};
-
 class ANDROID_API ResourceCache: public Singleton<ResourceCache> {
     ResourceCache();
     ~ResourceCache();
@@ -97,18 +66,10 @@
     void lock();
     void unlock();
 
-    /**
-     * The cache stores a copy of the provided resource or refs an existing resource
-     * if the bitmap has previously been inserted and returns the cached copy.
-     */
-    const SkBitmap* insert(const SkBitmap& resource);
-
     void incrementRefcount(const Res_png_9patch* resource);
 
-    void decrementRefcount(const SkBitmap* resource);
     void decrementRefcount(const Res_png_9patch* resource);
 
-    void decrementRefcountLocked(const SkBitmap* resource);
     void decrementRefcountLocked(const Res_png_9patch* resource);
 
     void destructor(Res_png_9patch* resource);
@@ -134,7 +95,6 @@
     mutable Mutex mLock;
 
     KeyedVector<const void*, ResourceReference*>* mCache;
-    KeyedVector<BitmapKey, SkBitmap*> mBitmapCache;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 3de3086..436946f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -16,36 +16,25 @@
 
 #include "CanvasContext.h"
 
+#include "AnimationContext.h"
+#include "Caches.h"
+#include "DeferredLayerUpdater.h"
 #include "EglManager.h"
+#include "LayerRenderer.h"
+#include "OpenGLRenderer.h"
+#include "Properties.h"
 #include "RenderThread.h"
-#include "../AnimationContext.h"
-#include "../Caches.h"
-#include "../DeferredLayerUpdater.h"
-#include "../renderstate/RenderState.h"
-#include "../renderstate/Stencil.h"
-#include "../LayerRenderer.h"
-#include "../OpenGLRenderer.h"
+#include "renderstate/RenderState.h"
+#include "renderstate/Stencil.h"
 
 #include <algorithm>
+#include <strings.h>
 #include <cutils/properties.h>
 #include <private/hwui/DrawGlInfo.h>
-#include <strings.h>
 
 #define TRIM_MEMORY_COMPLETE 80
 #define TRIM_MEMORY_UI_HIDDEN 20
 
-#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage"
-
-static bool sInitialized = false;
-static bool sSkipEmptyDamage = true;
-
-static void initGlobals() {
-    if (sInitialized) return;
-    sInitialized = true;
-    sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE,
-            sSkipEmptyDamage);
-}
-
 namespace android {
 namespace uirenderer {
 namespace renderthread {
@@ -58,9 +47,6 @@
         , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
         , mRootRenderNode(rootRenderNode)
         , mJankTracker(thread.timeLord().frameIntervalNanos()) {
-    // Done lazily at first draw instead of at library load to avoid
-    // running pre-zygote fork
-    initGlobals();
     mRenderThread.renderState().registerCanvasContext(this);
     mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
 }
@@ -106,8 +92,8 @@
     }
 }
 
-void CanvasContext::swapBuffers() {
-    if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) {
+void CanvasContext::swapBuffers(const SkRect& dirty, EGLint width, EGLint height) {
+    if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface, dirty, width, height))) {
         setSurface(nullptr);
     }
     mHaveNewSurface = false;
@@ -222,7 +208,7 @@
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
 
-    if (dirty.isEmpty() && sSkipEmptyDamage) {
+    if (dirty.isEmpty() && Properties::skipEmptyFrames) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame);
         return;
     }
@@ -267,7 +253,7 @@
     mCurrentFrameInfo->markSwapBuffers();
 
     if (drew) {
-        swapBuffers();
+        swapBuffers(dirty, width, height);
     } else {
         mEglManager.cancelFrame();
     }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index f5f1f54..8163b0f 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -29,6 +29,7 @@
 #include <cutils/compiler.h>
 #include <EGL/egl.h>
 #include <SkBitmap.h>
+#include <SkRect.h>
 #include <utils/Functor.h>
 #include <utils/Vector.h>
 
@@ -117,7 +118,7 @@
     friend class android::uirenderer::RenderState;
 
     void setSurface(ANativeWindow* window);
-    void swapBuffers();
+    void swapBuffers(const SkRect& dirty, EGLint width, EGLint height);
     void requireSurface();
 
     void requireGlContext();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 3afca2f..6255f5e 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -16,9 +16,10 @@
 
 #include "EglManager.h"
 
-#include "../Caches.h"
-#include "../renderstate/RenderState.h"
+#include "Caches.h"
+#include "Properties.h"
 #include "RenderThread.h"
+#include "renderstate/RenderState.h"
 
 #include <cutils/log.h>
 #include <cutils/properties.h>
@@ -261,7 +262,8 @@
     mInFrame = true;
 }
 
-bool EglManager::swapBuffers(EGLSurface surface) {
+bool EglManager::swapBuffers(EGLSurface surface, const SkRect& dirty,
+        EGLint width, EGLint height) {
     mInFrame = false;
 
 #if WAIT_FOR_GPU_COMPLETION
@@ -271,7 +273,37 @@
     }
 #endif
 
+#ifdef EGL_KHR_swap_buffers_with_damage
+    if (CC_UNLIKELY(Properties::swapBuffersWithDamage)) {
+        SkIRect idirty;
+        dirty.roundOut(&idirty);
+        /*
+         * EGL_KHR_swap_buffers_with_damage spec states:
+         *
+         * The rectangles are specified relative to the bottom-left of the surface
+         * and the x and y components of each rectangle specify the bottom-left
+         * position of that rectangle.
+         *
+         * HWUI does everything with 0,0 being top-left, so need to map
+         * the rect
+         */
+        EGLint y = height - (idirty.y() + idirty.height());
+        // layout: {x, y, width, height}
+        EGLint rects[4] = { idirty.x(), y, idirty.width(), idirty.height() };
+        EGLint numrects = dirty.isEmpty() ? 0 : 1;
+        // TODO: Remove prior to enabling this path by default
+        ALOGD("Swap buffers with damage %d: %d, %d, %d, %d (src="
+                RECT_STRING ")",
+                dirty.isEmpty() ? 0 : 1, rects[0], rects[1], rects[2], rects[3],
+                SK_RECT_ARGS(dirty));
+        eglSwapBuffersWithDamageKHR(mEglDisplay, surface, rects, numrects);
+    } else {
+        eglSwapBuffers(mEglDisplay, surface);
+    }
+#else
     eglSwapBuffers(mEglDisplay, surface);
+#endif
+
     EGLint err = eglGetError();
     if (CC_LIKELY(err == EGL_SUCCESS)) {
         return true;
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index b1a18a9..0855516 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -18,6 +18,7 @@
 
 #include <cutils/compiler.h>
 #include <EGL/egl.h>
+#include <SkRect.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
@@ -47,7 +48,7 @@
     // Returns true if the current surface changed, false if it was already current
     bool makeCurrent(EGLSurface surface);
     void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
-    bool swapBuffers(EGLSurface surface);
+    bool swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height);
     void cancelFrame();
 
     // Returns true iff the surface is now preserving buffers.
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c643e1d..17e47b9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -353,7 +353,6 @@
 }
 
 void RenderProxy::overrideProperty(const char* name, const char* value) {
-    RenderThread& thread = RenderThread::getInstance();
     SETUP_TASK(overrideProperty);
     args->name = name;
     args->value = value;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 6ec10c7..b3c1b4d 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2824,6 +2824,13 @@
                         mSubtitleController.selectDefaultTrack();
                     }
                     break;
+                case MEDIA_INFO_BUFFERING_START:
+                case MEDIA_INFO_BUFFERING_END:
+                    TimeProvider timeProvider = mTimeProvider;
+                    if (timeProvider != null) {
+                        timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START);
+                    }
+                    break;
                 }
 
                 if (mOnInfoListener != null) {
@@ -3362,6 +3369,7 @@
         private MediaPlayer mPlayer;
         private boolean mPaused = true;
         private boolean mStopped = true;
+        private boolean mBuffering;
         private long mLastReportedTime;
         private long mTimeAdjustment;
         // since we are expecting only a handful listeners per stream, there is
@@ -3455,12 +3463,22 @@
         }
 
         /** @hide */
+        public void onBuffering(boolean buffering) {
+            synchronized (this) {
+                if (DEBUG) Log.d(TAG, "onBuffering: " + buffering);
+                mBuffering = buffering;
+                scheduleNotification(REFRESH_AND_NOTIFY_TIME, 0 /* delay */);
+            }
+        }
+
+        /** @hide */
         public void onStopped() {
             synchronized(this) {
                 if (DEBUG) Log.d(TAG, "onStopped");
                 mPaused = true;
                 mStopped = true;
                 mSeeking = false;
+                mBuffering = false;
                 scheduleNotification(NOTIFY_STOP, 0 /* delay */);
             }
         }
@@ -3481,6 +3499,7 @@
                 synchronized(this) {
                     mStopped = false;
                     mSeeking = true;
+                    mBuffering = false;
                     scheduleNotification(NOTIFY_SEEK, 0 /* delay */);
                 }
             }
@@ -3683,7 +3702,7 @@
                         nanoTime >= mLastNanoTime + MAX_NS_WITHOUT_POSITION_CHECK) {
                     try {
                         mLastTimeUs = mPlayer.getCurrentPosition() * 1000L;
-                        mPaused = !mPlayer.isPlaying();
+                        mPaused = !mPlayer.isPlaying() || mBuffering;
                         if (DEBUG) Log.v(TAG, (mPaused ? "paused" : "playing") + " at " + mLastTimeUs);
                     } catch (IllegalStateException e) {
                         if (mPausing) {
diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
index 35374ed..57607e9 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -298,6 +298,9 @@
 
     @Override
     public String toString() {
+        // This is a hack to force the mProperties Bundle to unparcel so we can
+        // print all the names and values.
+        mProperties.getString(PROPERTY_NAME);
         return ("MidiDeviceInfo[mType=" + mType +
                 ",mInputPortCount=" + mInputPortCount +
                 ",mOutputPortCount=" + mOutputPortCount +
diff --git a/media/java/android/media/midi/MidiDeviceStatus.java b/media/java/android/media/midi/MidiDeviceStatus.java
index 7522dcf..d4abeff 100644
--- a/media/java/android/media/midi/MidiDeviceStatus.java
+++ b/media/java/android/media/midi/MidiDeviceStatus.java
@@ -89,10 +89,9 @@
 
     @Override
     public String toString() {
-        StringBuilder builder = new StringBuilder(mDeviceInfo.toString());
         int inputPortCount = mDeviceInfo.getInputPortCount();
         int outputPortCount = mDeviceInfo.getOutputPortCount();
-        builder.append(" mInputPortOpen=[");
+        StringBuilder builder = new StringBuilder("mInputPortOpen=[");
         for (int i = 0; i < inputPortCount; i++) {
             builder.append(mInputPortOpen[i]);
             if (i < inputPortCount -1) {
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
index fa5e5e0..5823057 100644
--- a/media/jni/android_media_MediaSync.h
+++ b/media/jni/android_media_MediaSync.h
@@ -26,7 +26,7 @@
 
 struct AudioPlaybackRate;
 class AudioTrack;
-struct IGraphicBufferProducer;
+class IGraphicBufferProducer;
 struct MediaClock;
 class MediaSync;
 
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 4e7c6be..26b41e8 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -35,9 +35,27 @@
 using android::SensorManager;
 using android::SensorEventQueue;
 using android::String8;
+using android::String16;
 
 /*****************************************************************************/
 
+android::Mutex android::SensorManager::sLock;
+std::map<String16, SensorManager*> android::SensorManager::sPackageInstances;
+
+ASensorManager* ASensorManager_getInstance()
+{
+    return ASensorManager_getInstanceForPackage(NULL);
+}
+
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName)
+{
+    if (packageName) {
+        return &SensorManager::getInstanceForPackage(String16(packageName));
+    } else {
+        return &SensorManager::getInstanceForPackage(String16());
+    }
+}
+
 int ASensorManager_getSensorList(ASensorManager* manager,
         ASensorList* list)
 {
diff --git a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
index a11bed0..2f0a411 100644
--- a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
+++ b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
@@ -10,6 +10,13 @@
     android:layout_height="match_parent"
     android:orientation="vertical" >
 
+    <TextView
+        android:id="@+id/url_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="20sp"
+        android:singleLine="true" />
+
     <ProgressBar
         android:id="@+id/progress_bar"
         android:layout_width="match_parent"
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index b86fc4b..1019e6c 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -35,13 +35,13 @@
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 import android.widget.ProgressBar;
+import android.widget.TextView;
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
@@ -221,6 +221,7 @@
     }
 
     private class MyWebViewClient extends WebViewClient {
+        private static final String INTERNAL_ASSETS = "file:///android_asset/";
         private boolean firstPageLoad = true;
 
         @Override
@@ -240,6 +241,12 @@
                 view.loadUrl(mURL.toString());
                 return;
             }
+            // For internally generated pages, leave URL bar listing prior URL as this is the URL
+            // the page refers to.
+            if (!url.startsWith(INTERNAL_ASSETS)) {
+                final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+                myUrlBar.setText(url);
+            }
             testForCaptivePortal();
         }
 
@@ -252,17 +259,15 @@
         @Override
         public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
             Log.w(TAG, "SSL error; displaying broken lock icon.");
-            view.loadDataWithBaseURL("file:///android_asset/", SSL_ERROR_HTML, "text/HTML",
-                    "UTF-8", null);
+            view.loadDataWithBaseURL(INTERNAL_ASSETS, SSL_ERROR_HTML, "text/HTML", "UTF-8", null);
         }
     }
 
     private class MyWebChromeClient extends WebChromeClient {
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
-            ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+            final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
             myProgressBar.setProgress(newProgress);
-            myProgressBar.setVisibility(newProgress == 100 ? View.GONE : View.VISIBLE);
         }
     }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index b5eda90..1c4b963 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -16,6 +16,7 @@
 
 package com.android.keyguard;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -25,12 +26,15 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewHierarchyEncoder;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ViewFlipper;
 
 import com.android.internal.widget.LockPatternUtils;
 
+import java.lang.Override;
+
 /**
  * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
  * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy.
@@ -268,5 +272,14 @@
                     R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxHeight, 0);
             a.recycle();
         }
+
+        /** @hide */
+        @Override
+        protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
+            super.encodeProperties(encoder);
+
+            encoder.addProperty("layout:maxWidth", maxWidth);
+            encoder.addProperty("layout:maxHeight", maxHeight);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b5c1ca8..f352849 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -33,6 +33,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.DetailAdapter;
@@ -182,8 +183,11 @@
     public void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
+        MetricsLogger.visibility(mContext, MetricsLogger.QS_PANEL, mExpanded);
         if (!mExpanded) {
             closeDetail();
+        } else {
+            logTiles();
         }
     }
 
@@ -365,9 +369,11 @@
             mDetailContent.removeAllViews();
             mDetail.bringToFront();
             mDetailContent.addView(r.detailView);
+            MetricsLogger.visible(mContext, detailAdapter.getMetricsCategory());
             setDetailRecord(r);
             listener = mHideGridContentWhenDone;
         } else {
+            MetricsLogger.hidden(mContext, mDetailRecord.detailAdapter.getMetricsCategory());
             mClosingDetail = true;
             setGridContentVisibility(true);
             listener = mTeardownDetailWhenDone;
@@ -387,9 +393,21 @@
             }
         }
         mBrightnessView.setVisibility(newVis);
+        if (mGridContentVisible != visible) {
+            MetricsLogger.visibility(mContext, MetricsLogger.QS_PANEL, newVis);
+        }
         mGridContentVisible = visible;
     }
 
+    private void logTiles() {
+        for (int i = 0; i < mRecords.size(); i++) {
+            TileRecord tileRecord = mRecords.get(i);
+            if (tileRecord.tile.getState().visible) {
+                MetricsLogger.visible(mContext, tileRecord.tile.getMetricsCategory());
+            }
+        }
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int width = MeasureSpec.getSize(widthMeasureSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index b9574dc..452fd44 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -29,6 +29,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.qs.QSTile.State;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
@@ -66,9 +67,17 @@
     private boolean mAnnounceNextStateChange;
 
     abstract protected TState newTileState();
-    abstract protected void handleClick();
     abstract protected void handleUpdateState(TState state, Object arg);
 
+    /**
+     * Declare the category of this tile.
+     *
+     * Categories are defined in {@link com.android.internal.logging.MetricsLogger}
+     * or if there is no relevant existing category you may define one in
+     * {@link com.android.systemui.qs.QSTile}.
+     */
+    abstract public int getMetricsCategory();
+
     protected QSTile(Host host) {
         mHost = host;
         mContext = host.getContext();
@@ -97,6 +106,7 @@
         View createDetailView(Context context, View convertView, ViewGroup parent);
         Intent getSettingsIntent();
         void setToggleState(boolean state);
+        int getMetricsCategory();
     }
 
     // safe to call from any thread
@@ -160,6 +170,10 @@
         handleRefreshState(null);
     }
 
+    protected void handleClick() {
+        MetricsLogger.action(mContext, getMetricsCategory(), getMetricsPackage());
+    };
+
     protected void handleSecondaryClick() {
         // optional
     }
@@ -168,6 +182,10 @@
         // optional
     }
 
+    protected String getMetricsPackage() {
+        return "";
+    }
+
     protected void handleRefreshState(Object arg) {
         handleUpdateState(mTmpState, arg);
         final boolean changed = mTmpState.copyTo(mState);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 2bc31fc..6744154 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -23,6 +23,7 @@
 import android.net.ConnectivityManager;
 import android.provider.Settings.Global;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSTile;
@@ -55,6 +56,7 @@
 
     @Override
     public void handleClick() {
+        super.handleClick();
         setEnabled(!mState.value);
         mEnable.setAllowAnimation(true);
         mDisable.setAllowAnimation(true);
@@ -85,6 +87,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_AIRPLANEMODE;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_airplane_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index b42b5f6..8eb624f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -25,6 +25,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
@@ -74,6 +75,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         final boolean isEnabled = (Boolean)mState.value;
         mController.setBluetoothEnabled(!isEnabled);
     }
@@ -132,6 +134,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_BLUETOOTH;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_on);
@@ -182,6 +189,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_BLUETOOTH_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
             mItems.setTagSuffix("Bluetooth");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 5bf6fb5..a3d7bcc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -24,6 +24,7 @@
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
@@ -85,6 +86,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         showDetail(true);
     }
 
@@ -113,6 +115,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_CAST;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (!mState.value) {
             // We only announce when it's turned off to avoid vocal overflow.
@@ -164,6 +171,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_CAST_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
             mItems.setTagSuffix("Cast");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 30f92b9..0026141 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,6 +24,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTileView;
@@ -75,6 +76,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         if (mDataController.isMobileDataSupported()) {
             showDetail(true);
         } else {
@@ -118,6 +120,11 @@
                 state.label);
     }
 
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_CELLULAR;
+    }
+
     // Remove the period from the network name
     public static String removeTrailingPeriod(String string) {
         if (string == null) return null;
@@ -227,6 +234,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_DATAUSAGEDETAIL;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
                     ? convertView
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 4a33f55..6fa094e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -18,6 +18,7 @@
 
 import android.provider.Settings.Secure;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -86,6 +87,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         mSetting.setValue(mState.value ? 0 : 1);
         mEnable.setAllowAnimation(true);
         mDisable.setAllowAnimation(true);
@@ -115,6 +117,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_COLORINVERSION;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(
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 5145bc7..e708a72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -29,6 +29,7 @@
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -88,6 +89,7 @@
 
     @Override
     public void handleClick() {
+        super.handleClick();
         if (mState.value) {
             mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
         } else {
@@ -135,6 +137,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_DND;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
@@ -209,6 +216,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_DND_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
                     : (ZenModePanel) LayoutInflater.from(context).inflate(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index cb78deb..a1f3cde 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.FlashlightController;
@@ -59,6 +60,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         if (ActivityManager.isUserAMonkey()) {
             return;
         }
@@ -84,6 +86,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_FLASHLIGHT;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 6063f80..b864ff4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.UsageTracker;
@@ -68,6 +69,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         final boolean isEnabled = (Boolean) mState.value;
         mController.setHotspotEnabled(!isEnabled);
         mEnable.setAllowAnimation(true);
@@ -97,6 +99,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_HOTSPOT;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 2736530..20b5f04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -29,6 +29,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.qs.QSTile;
 
 import java.util.Arrays;
@@ -42,6 +43,7 @@
     private PendingIntent mOnLongClick;
     private String mOnLongClickUri;
     private int mCurrentUserId;
+    private String mIntentPackage;
 
     private IntentTile(Host host, String action) {
         super(host);
@@ -82,6 +84,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         sendIntent("click", mOnClick, mOnClickUri);
     }
 
@@ -133,6 +136,17 @@
         mOnClickUri = intent.getStringExtra("onClickUri");
         mOnLongClick = intent.getParcelableExtra("onLongClick");
         mOnLongClickUri = intent.getStringExtra("onLongClickUri");
+        mIntentPackage = intent.getStringExtra("package");
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_INTENT;
+    }
+
+    @Override
+    protected String getMetricsPackage() {
+        return mIntentPackage == null ? "" : mIntentPackage;
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 11ec722..ab22ada 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -58,6 +59,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         final boolean wasEnabled = (Boolean) mState.value;
         mController.setLocationEnabled(!wasEnabled);
         mEnable.setAllowAnimation(true);
@@ -87,6 +89,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_LOCATION;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_location_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index f46b9a6..7e3fe76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -18,6 +18,7 @@
 
 import android.content.res.Configuration;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.RotationLockController;
@@ -58,6 +59,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         if (mController == null) return;
         final boolean newState = !mState.value;
         mController.setRotationLocked(newState);
@@ -92,6 +94,11 @@
                 R.string.accessibility_rotation_lock_off);
     }
 
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_ROTATIONLOCK;
+    }
+
     /**
      * Get the correct accessibility string based on the state
      *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index d589366..228c293 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -26,6 +26,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
@@ -93,6 +94,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         mState.copyTo(mStateBeforeClick);
         mController.setWifiEnabled(!mState.enabled);
     }
@@ -159,6 +161,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_WIFI;
+    }
+
+    @Override
     protected boolean shouldAnnouncementBeDelayed() {
         return mStateBeforeClick.enabled == mState.enabled;
     }
@@ -274,6 +281,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_WIFI_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
             mAccessPoints = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 4542054..80fdd28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -157,7 +157,8 @@
 
     public void setSystemUiVisibility(int vis, int mask) {
         synchronized (mList) {
-            mHandler.removeMessages(MSG_SET_SYSTEMUI_VISIBILITY);
+            // Don't coalesce these, since it might have one time flags set such as
+            // STATUS_BAR_UNHIDE which might get lost.
             mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, vis, mask, null).sendToTarget();
         }
     }
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 351977b..471196c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -529,6 +529,7 @@
             = new HashMap<>();
     private HashSet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new HashSet<>();
     private RankingMap mLatestRankingMap;
+    private boolean mNoAnimationOnNextBarModeChange;
 
     @Override
     public void start() {
@@ -1709,6 +1710,7 @@
      * State is one or more of the DISABLE constants from StatusBarManager.
      */
     public void disable(int state1, int state2, boolean animate) {
+        animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
         mDisabledUnmodified1 = state1;
         mDisabledUnmodified2 = state2;
         state1 = adjustDisableFlags(state1);
@@ -1868,6 +1870,7 @@
     public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
         if (inPinnedMode) {
             mStatusBarWindowManager.setHeadsUpShowing(true);
+            mStatusBarWindowManager.setForceStatusBarVisible(true);
         } else {
             Runnable endRunnable = new Runnable() {
                 @Override
@@ -2132,6 +2135,7 @@
 
         // Shrink the window to the size of the status bar only
         mStatusBarWindowManager.setStatusBarExpanded(false);
+        mStatusBarWindowManager.setForceStatusBarVisible(false);
         mStatusBarView.setFocusable(true);
 
         // Close any "App info" popups that might have snuck on-screen
@@ -2272,6 +2276,12 @@
                 setAreThereNotifications();
             }
 
+            // ready to unhide
+            if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
+                mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
+                mNoAnimationOnNextBarModeChange = true;
+            }
+
             // update status bar mode
             final int sbMode = computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),
                     View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT);
@@ -2303,10 +2313,6 @@
                 }
             }
 
-            // ready to unhide
-            if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
-                mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
-            }
             if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
                 mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
             }
@@ -2351,17 +2357,21 @@
 
     private void checkBarModes() {
         if (mDemoMode) return;
-        checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarView.getBarTransitions());
+        checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarView.getBarTransitions(),
+                mNoAnimationOnNextBarModeChange);
         if (mNavigationBarView != null) {
             checkBarMode(mNavigationBarMode,
-                    mNavigationBarWindowState, mNavigationBarView.getBarTransitions());
+                    mNavigationBarWindowState, mNavigationBarView.getBarTransitions(),
+                    mNoAnimationOnNextBarModeChange);
         }
+        mNoAnimationOnNextBarModeChange = false;
     }
 
-    private void checkBarMode(int mode, int windowState, BarTransitions transitions) {
+    private void checkBarMode(int mode, int windowState, BarTransitions transitions,
+            boolean noAnimation) {
         final boolean powerSave = mBatteryController.isPowerSave();
-        final boolean anim = (mScreenOn == null || mScreenOn) && windowState != WINDOW_STATE_HIDDEN
-                && !powerSave;
+        final boolean anim = !noAnimation && (mScreenOn == null || mScreenOn)
+                && windowState != WINDOW_STATE_HIDDEN && !powerSave;
         if (powerSave && getBarState() == StatusBarState.SHADE) {
             mode = MODE_WARNING;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 84a9f64..e7e4384 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -166,6 +166,7 @@
 
     private void apply(State state) {
         applyKeyguardFlags(state);
+        applyForceStatusBarVisibleFlag(state);
         applyFocusableFlag(state);
         adjustScreenOrientation(state);
         applyHeight(state);
@@ -178,6 +179,16 @@
         }
     }
 
+    private void applyForceStatusBarVisibleFlag(State state) {
+        if (state.forceStatusBarVisible) {
+            mLpChanged.privateFlags |= WindowManager
+                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+        } else {
+            mLpChanged.privateFlags &= ~WindowManager
+                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+        }
+    }
+
     private void applyModalFlag(State state) {
         if (state.headsUpShowing) {
             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -240,6 +251,11 @@
         apply(mCurrentState);
     }
 
+    public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
+        mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
+        apply(mCurrentState);
+    }
+
     private static class State {
         boolean keyguardShowing;
         boolean keyguardOccluded;
@@ -250,6 +266,7 @@
         boolean keyguardFadingAway;
         boolean qsExpanded;
         boolean headsUpShowing;
+        boolean forceStatusBarVisible;
 
         /**
          * The {@link BaseStatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 194bcfa..ad27c6e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -43,6 +43,7 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.UserIcons;
 import com.android.systemui.BitmapHelper;
 import com.android.systemui.GuestResumeSessionReceiver;
@@ -548,6 +549,11 @@
         @Override
         public void setToggleState(boolean state) {
         }
+
+        @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_USERDETAIL;
+        }
     };
 
     private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 58d0fce..a49fb76 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1857,7 +1857,7 @@
                jintArray limits)
 {
     if (kLogApi) {
-        ALOGD("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%lli)", (RsContext)con, (void *)script, slot, ains, aout);
+        ALOGD("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
     }
 
     jint   in_len = 0;
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 26f4232..ebc810f 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -119,7 +119,6 @@
     // long0: SkBitmap*, the native bitmap object
     // long1: x position
     // long2: y position
-    // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
     private long[] mAtlasMap;
 
     /**
@@ -236,7 +235,7 @@
         /**
          * Renders a list of bitmaps into the atlas. The position of each bitmap
          * was decided by the packing algorithm and will be honored by this
-         * method. If need be this method will also rotate bitmaps.
+         * method.
          *
          * @param buffer The buffer to render the atlas entries into
          * @param atlas The atlas to pack the bitmaps into
@@ -280,16 +279,11 @@
 
                     canvas.save();
                     canvas.translate(entry.x, entry.y);
-                    if (entry.rotated) {
-                        canvas.translate(bitmap.getHeight(), 0.0f);
-                        canvas.rotate(90.0f);
-                    }
                     canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
                     canvas.restore();
                     atlasMap[mapIndex++] = bitmap.refSkPixelRef();
                     atlasMap[mapIndex++] = entry.x;
                     atlasMap[mapIndex++] = entry.y;
-                    atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
                 }
             }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8d1d124..1dc2d7e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -190,7 +190,7 @@
     /** Set of ifaces that are costly. */
     private HashSet<String> mMeteredIfaces = Sets.newHashSet();
 
-    private Context mContext;
+    final private Context mContext;
     private int mNetworkPreference;
     // 0 is full bad, 100 is full good
     private int mDefaultInetConditionPublished = 0;
@@ -344,6 +344,11 @@
      */
     private static final int EVENT_PROMPT_UNVALIDATED = 29;
 
+    /**
+     * used internally to (re)configure mobile data always-on settings.
+     */
+    private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
+
     /** Handler used for internal events. */
     final private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -374,7 +379,7 @@
 
     private PacManager mPacManager = null;
 
-    private SettingsObserver mSettingsObserver;
+    final private SettingsObserver mSettingsObserver;
 
     private UserManager mUserManager;
 
@@ -555,13 +560,12 @@
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         if (DBG) log("ConnectivityService starting up");
 
-        NetworkCapabilities netCap = new NetworkCapabilities();
-        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
-        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
-        mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
-        NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
-                NetworkRequestInfo.REQUEST);
-        mNetworkRequests.put(mDefaultRequest, nri);
+        mDefaultRequest = createInternetRequestForTransport(-1);
+        mNetworkRequests.put(mDefaultRequest, new NetworkRequestInfo(
+                null, mDefaultRequest, new Binder(), NetworkRequestInfo.REQUEST));
+
+        mDefaultMobileDataRequest = createInternetRequestForTransport(
+                NetworkCapabilities.TRANSPORT_CELLULAR);
 
         HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
         handlerThread.start();
@@ -696,8 +700,8 @@
             mInetLog = new ArrayList();
         }
 
-        mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
-        mSettingsObserver.observe(mContext);
+        mSettingsObserver = new SettingsObserver(mContext, mHandler);
+        registerSettingsCallbacks();
 
         mDataConnectionStats = new DataConnectionStats(mContext);
         mDataConnectionStats.startMonitoring();
@@ -707,6 +711,44 @@
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
 
+    private NetworkRequest createInternetRequestForTransport(int transportType) {
+        NetworkCapabilities netCap = new NetworkCapabilities();
+        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+        if (transportType > -1) {
+            netCap.addTransportType(transportType);
+        }
+        return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
+    }
+
+    private void handleMobileDataAlwaysOn() {
+        final boolean enable = (Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1);
+        final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
+        if (enable == isEnabled) {
+            return;  // Nothing to do.
+        }
+
+        if (enable) {
+            handleRegisterNetworkRequest(new NetworkRequestInfo(
+                    null, mDefaultMobileDataRequest, new Binder(), NetworkRequestInfo.REQUEST));
+        } else {
+            handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
+        }
+    }
+
+    private void registerSettingsCallbacks() {
+        // Watch for global HTTP proxy changes.
+        mSettingsObserver.observe(
+                Settings.Global.getUriFor(Settings.Global.HTTP_PROXY),
+                EVENT_APPLY_GLOBAL_HTTP_PROXY);
+
+        // Watch for whether or not to keep mobile data always on.
+        mSettingsObserver.observe(
+                Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
+                EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
+    }
+
     private synchronized int nextNetworkRequestId() {
         return mNextNetworkRequestId++;
     }
@@ -1491,6 +1533,9 @@
             mContext.registerReceiver(mUserPresentReceiver, filter);
         }
 
+        // Configure whether mobile data is always on.
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON));
+
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
 
         mPermissionMonitor.startMonitoring();
@@ -2107,12 +2152,10 @@
                     + nri.request + " because their intents matched.");
             handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
         }
-        handleRegisterNetworkRequest(msg);
+        handleRegisterNetworkRequest(nri);
     }
 
-    private void handleRegisterNetworkRequest(Message msg) {
-        final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
-
+    private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
         mNetworkRequests.put(nri.request, nri);
 
         // TODO: This logic may be better replaced with a call to rematchNetworkAndRequests
@@ -2423,7 +2466,7 @@
                 }
                 case EVENT_REGISTER_NETWORK_REQUEST:
                 case EVENT_REGISTER_NETWORK_LISTENER: {
-                    handleRegisterNetworkRequest(msg);
+                    handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
                     break;
                 }
                 case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
@@ -2446,6 +2489,10 @@
                     handlePromptUnvalidated((Network) msg.obj);
                     break;
                 }
+                case EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON: {
+                    handleMobileDataAlwaysOn();
+                    break;
+                }
                 case EVENT_SYSTEM_READY: {
                     for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
                         nai.networkMonitor.systemReady = true;
@@ -2837,23 +2884,36 @@
     }
 
     private static class SettingsObserver extends ContentObserver {
-        private int mWhat;
-        private Handler mHandler;
-        SettingsObserver(Handler handler, int what) {
-            super(handler);
+        final private HashMap<Uri, Integer> mUriEventMap;
+        final private Context mContext;
+        final private Handler mHandler;
+
+        SettingsObserver(Context context, Handler handler) {
+            super(null);
+            mUriEventMap = new HashMap<Uri, Integer>();
+            mContext = context;
             mHandler = handler;
-            mWhat = what;
         }
 
-        void observe(Context context) {
-            ContentResolver resolver = context.getContentResolver();
-            resolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.HTTP_PROXY), false, this);
+        void observe(Uri uri, int what) {
+            mUriEventMap.put(uri, what);
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(uri, false, this);
         }
 
         @Override
         public void onChange(boolean selfChange) {
-            mHandler.obtainMessage(mWhat).sendToTarget();
+            Slog.wtf(TAG, "Should never be reached.");
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            final Integer what = mUriEventMap.get(uri);
+            if (what != null) {
+                mHandler.obtainMessage(what.intValue()).sendToTarget();
+            } else {
+                loge("No matching event to send for URI=" + uri);
+            }
         }
     }
 
@@ -3643,6 +3703,10 @@
     // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
     private final NetworkRequest mDefaultRequest;
 
+    // Request used to optionally keep mobile data active even when higher
+    // priority networks like Wi-Fi are active.
+    private final NetworkRequest mDefaultMobileDataRequest;
+
     private NetworkAgentInfo getDefaultNetwork() {
         return mNetworkForRequestId.get(mDefaultRequest.requestId);
     }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 9511f54..e856a93 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1695,6 +1695,7 @@
                     vis = 0;
                 }
                 mImeWindowVis = vis;
+                mInputShown = ((mImeWindowVis & InputMethodService.IME_VISIBLE) != 0);
                 mBackDisposition = backDisposition;
                 final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0)
                         && (mWindowManagerService.isHardKeyboardAvailable()
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 82dbfee..d1df7e2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14121,6 +14121,7 @@
         boolean dumpDetails = false;
         boolean dumpFullDetails = false;
         boolean dumpDalvik = false;
+        boolean dumpSummaryOnly = false;
         boolean oomOnly = false;
         boolean isCompact = false;
         boolean localOnly = false;
@@ -14141,6 +14142,9 @@
                 dumpDalvik = true;
             } else if ("-c".equals(opt)) {
                 isCompact = true;
+            } else if ("-s".equals(opt)) {
+                dumpDetails = true;
+                dumpSummaryOnly = true;
             } else if ("--oom".equals(opt)) {
                 oomOnly = true;
             } else if ("--local".equals(opt)) {
@@ -14148,10 +14152,11 @@
             } else if ("--package".equals(opt)) {
                 packages = true;
             } else if ("-h".equals(opt)) {
-                pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]");
+                pw.println("meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]");
                 pw.println("  -a: include all available information for each process.");
                 pw.println("  -d: include dalvik details.");
                 pw.println("  -c: dump in a compact machine-parseable representation.");
+                pw.println("  -s: dump only summary of application memory usage.");
                 pw.println("  --oom: only show processes organized by oom adj.");
                 pw.println("  --local: only collect details locally, don't call process.");
                 pw.println("  --package: interpret process arg as package, dumping all");
@@ -14212,7 +14217,7 @@
                             mi.dalvikPrivateDirty = (int)tmpLong[0];
                         }
                         ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
-                                dumpDalvik, pid, r.baseName, 0, 0, 0, 0, 0, 0);
+                                dumpDalvik, dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0);
                         if (isCheckinRequest) {
                             pw.println();
                         }
@@ -14278,7 +14283,7 @@
                 if (dumpDetails) {
                     if (localOnly) {
                         ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
-                                dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0);
+                                dumpDalvik, dumpSummaryOnly, pid, r.processName, 0, 0, 0, 0, 0, 0);
                         if (isCheckinRequest) {
                             pw.println();
                         }
@@ -14286,7 +14291,7 @@
                         try {
                             pw.flush();
                             thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
-                                    dumpDalvik, innerArgs);
+                                    dumpDalvik, dumpSummaryOnly, innerArgs);
                         } catch (RemoteException e) {
                             if (!isCheckinRequest) {
                                 pw.println("Got RemoteException!");
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 6f59b54..7f961ae 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -82,7 +82,7 @@
             appToken.linkToDeath(device, 0);
         } catch (RemoteException ex) {
             mVirtualDisplayDevices.remove(appToken);
-            device.destroyLocked();
+            device.destroyLocked(false);
             return null;
         }
 
@@ -110,7 +110,7 @@
     public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
         VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
         if (device != null) {
-            device.destroyLocked();
+            device.destroyLocked(true);
             appToken.unlinkToDeath(device, 0);
         }
 
@@ -147,7 +147,7 @@
         if (device != null) {
             Slog.i(TAG, "Virtual display device released because application token died: "
                     + device.mOwnerPackageName);
-            device.destroyLocked();
+            device.destroyLocked(false);
             sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
         }
     }
@@ -205,19 +205,19 @@
         @Override
         public void binderDied() {
             synchronized (getSyncRoot()) {
-                if (mSurface != null) {
-                    handleBinderDiedLocked(mAppToken);
-                }
+                handleBinderDiedLocked(mAppToken);
             }
         }
 
-        public void destroyLocked() {
+        public void destroyLocked(boolean binderAlive) {
             if (mSurface != null) {
                 mSurface.release();
                 mSurface = null;
             }
             SurfaceControl.destroyDisplay(getDisplayTokenLocked());
-            mCallback.dispatchDisplayStopped();
+            if (binderAlive) {
+                mCallback.dispatchDisplayStopped();
+            }
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f30a567..a120c1f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11853,6 +11853,7 @@
         synchronized (mPackages) {
             if (deletedPs != null) {
                 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
+                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                     if (outInfo != null) {
                         mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
                         outInfo.removedAppId = mSettings.removePackageLPw(packageName);
@@ -11883,7 +11884,6 @@
                         }
                     }
                     clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
-                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                 }
                 // make sure to preserve per-user disabled state if this removal was just
                 // a downgrade of a system app to the factory package
@@ -12744,13 +12744,16 @@
     /** This method takes a specific user id as well as UserHandle.USER_ALL. */
     void clearIntentFilterVerificationsLPw(String packageName, int userId) {
         if (userId == UserHandle.USER_ALL) {
-            mSettings.removeIntentFilterVerificationLPw(packageName, sUserManager.getUserIds());
-            for (int oneUserId : sUserManager.getUserIds()) {
-                scheduleWritePackageRestrictionsLocked(oneUserId);
+            if (mSettings.removeIntentFilterVerificationLPw(packageName,
+                    sUserManager.getUserIds())) {
+                for (int oneUserId : sUserManager.getUserIds()) {
+                    scheduleWritePackageRestrictionsLocked(oneUserId);
+                }
             }
         } else {
-            mSettings.removeIntentFilterVerificationLPw(packageName, userId);
-            scheduleWritePackageRestrictionsLocked(userId);
+            if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) {
+                scheduleWritePackageRestrictionsLocked(userId);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d476bfde..fd70ce1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1067,19 +1067,22 @@
         return result;
     }
 
-    void removeIntentFilterVerificationLPw(String packageName, int userId) {
+    boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
         PackageSetting ps = mPackages.get(packageName);
         if (ps == null) {
             Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
-            return;
+            return false;
         }
         ps.clearDomainVerificationStatusForUser(userId);
+        return true;
     }
 
-    void removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
+    boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
+        boolean result = false;
         for (int userId : userIds) {
-            removeIntentFilterVerificationLPw(packageName, userId);
+            result |= removeIntentFilterVerificationLPw(packageName, userId);
         }
+        return result;
     }
 
     boolean setDefaultBrowserPackageNameLPr(String packageName, int userId) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e79a206..e6f5e3d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -234,6 +234,14 @@
                 mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
                 initDefaultGuestRestrictions();
                 readUserListLocked();
+                sInstance = this;
+            }
+        }
+    }
+
+    void systemReady() {
+        synchronized (mInstallLock) {
+            synchronized (mPackagesLock) {
                 // Prune out any partially created/partially removed users.
                 ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
                 for (int i = 0; i < mUsers.size(); i++) {
@@ -248,12 +256,8 @@
                             + " (name=" + ui.name + ")");
                     removeUserStateLocked(ui.id);
                 }
-                sInstance = this;
             }
         }
-    }
-
-    void systemReady() {
         userForeground(UserHandle.USER_OWNER);
         mAppOpsService = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index e972ec7..5877b3e 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -58,6 +58,9 @@
     private int mTransientBarState;
     private boolean mPendingShow;
     private long mLastTranslucent;
+    private boolean mShowTransparent;
+    private boolean mSetUnHideFlagWhenNextTransparent;
+    private boolean mNoAnimationOnNextShow;
 
     public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
             int statusBarManagerId, int translucentWmFlag) {
@@ -74,6 +77,14 @@
         mWin = win;
     }
 
+    public void setShowTransparent(boolean transparent) {
+        if (transparent != mShowTransparent) {
+            mShowTransparent = transparent;
+            mSetUnHideFlagWhenNextTransparent = transparent;
+            mNoAnimationOnNextShow = true;
+        }
+    }
+
     public void showTransient() {
         if (mWin != null) {
             setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED);
@@ -135,7 +146,9 @@
         }
         final boolean wasVis = mWin.isVisibleLw();
         final boolean wasAnim = mWin.isAnimatingLw();
-        final boolean change = show ? mWin.showLw(true) : mWin.hideLw(true);
+        final boolean change = show ? mWin.showLw(!mNoAnimationOnNextShow)
+                : mWin.hideLw(!mNoAnimationOnNextShow);
+        mNoAnimationOnNextShow = false;
         final int state = computeStateLw(wasVis, wasAnim, mWin, change);
         final boolean stateChanged = updateStateLw(state);
         return change || stateChanged;
@@ -233,6 +246,13 @@
                 setTransientBarState(TRANSIENT_BAR_NONE);  // request denied
             }
         }
+        if (mShowTransparent) {
+            vis |= View.SYSTEM_UI_TRANSPARENT;
+            if (mSetUnHideFlagWhenNextTransparent) {
+                vis |= mUnhideFlag;
+                mSetUnHideFlagWhenNextTransparent = false;
+            }
+        }
         if (mTransientBarState != TRANSIENT_BAR_NONE) {
             vis |= mTransientFlag;  // ignore clear requests until transition completes
             vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;  // never show transient bars in low profile
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index b431b33..3cee927 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -1138,7 +1138,7 @@
 
         public GlobalActionsDialog(Context context, AlertParams params) {
             super(context, getDialogTheme(context));
-            mContext = context;
+            mContext = getContext();
             mAlert = new AlertController(mContext, this, getWindow());
             mAdapter = (MyAdapter) params.mAdapter;
             mWindowTouchSlop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index dbd3676..185ef03 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -476,6 +476,7 @@
     boolean mTopIsFullscreen;
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
+    private boolean mForceStatusBarTransparent;
     boolean mHideLockScreen;
     boolean mForcingShowNavBar;
     int mForcingShowNavBarLayer;
@@ -4129,6 +4130,7 @@
         mAppsThatDismissKeyguard.clear();
         mForceStatusBar = false;
         mForceStatusBarFromKeyguard = false;
+        mForceStatusBarTransparent = false;
         mForcingShowNavBar = false;
         mForcingShowNavBarLayer = -1;
 
@@ -4154,8 +4156,13 @@
             mForcingShowNavBar = true;
             mForcingShowNavBarLayer = win.getSurfaceLayer();
         }
-        if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-            mForceStatusBarFromKeyguard = true;
+        if (attrs.type == TYPE_STATUS_BAR) {
+            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                mForceStatusBarFromKeyguard = true;
+            }
+            if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
+                mForceStatusBarTransparent = true;
+            }
         }
 
         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
@@ -4302,7 +4309,15 @@
             if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
                     + " forcefkg=" + mForceStatusBarFromKeyguard
                     + " top=" + mTopFullscreenOpaqueWindowState);
-            if (mForceStatusBar || mForceStatusBarFromKeyguard) {
+            boolean shouldBeTransparent = mForceStatusBarTransparent
+                    && !mForceStatusBar
+                    && !mForceStatusBarFromKeyguard;
+            if (!shouldBeTransparent) {
+                mStatusBarController.setShowTransparent(false /* transparent */);
+            } else if (!mStatusBar.isVisibleLw()) {
+                mStatusBarController.setShowTransparent(true /* transparent */);
+            }
+            if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
                 if (mStatusBarController.setBarShowingLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6f01ca0..67c198f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2897,7 +2897,7 @@
 
         boolean callerIsDeviceOwnerAdmin = isCallerDeviceOwnerOrInitializer(callingUid);
         boolean doNotAskCredentialsOnBoot =
-                (flags & DevicePolicyManager.DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
+                (flags & DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
         if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) {
             setDoNotAskCredentialsOnBoot();
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2d265e2..925a609 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.content.res.Resources.Theme;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
@@ -291,7 +292,7 @@
     private void createSystemContext() {
         ActivityThread activityThread = ActivityThread.systemMain();
         mSystemContext = activityThread.getSystemContext();
-        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
+        mSystemContext.setTheme(android.R.style.Theme_Material_DayNight_DarkActionBar);
     }
 
     /**
@@ -1026,6 +1027,12 @@
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
 
+        // The system context's theme may be configuration-dependent.
+        final Theme systemTheme = context.getTheme();
+        if (systemTheme.getChangingConfigurations() != 0) {
+            systemTheme.rebase();
+        }
+
         try {
             // TODO: use boot phase
             mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index c1c5c56..176f54b 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -294,8 +294,10 @@
 
         @Override
         public String toString() {
-            StringBuilder sb = new StringBuilder("Device: ");
+            StringBuilder sb = new StringBuilder("Device Info: ");
             sb.append(mDeviceInfo);
+            sb.append(" Status: ");
+            sb.append(mDeviceStatus);
             sb.append(" UID: ");
             sb.append(mUid);
             return sb.toString();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 2897c61..fcdb6d6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -754,7 +754,7 @@
         public boolean activeServiceSupportsAssist() {
             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
             synchronized (this) {
-                return mImpl != null && mImpl.mInfo.getSupportsAssist();
+                return mImpl != null && mImpl.mInfo != null && mImpl.mInfo.getSupportsAssist();
             }
         }
 
@@ -762,7 +762,8 @@
         public boolean activeServiceSupportsLaunchFromKeyguard() throws RemoteException {
             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
             synchronized (this) {
-                return mImpl != null && mImpl.mInfo.getSupportsLaunchFromKeyguard();
+                return mImpl != null && mImpl.mInfo != null
+                        && mImpl.mInfo.getSupportsLaunchFromKeyguard();
             }
         }
 
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 0424548..e682697 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -179,7 +179,6 @@
 
     /**
      * Returns VideoProvider of the primary call. This can be null.
-     *  @hide
      */
     public VideoProvider getVideoProvider() {
         return null;
@@ -187,7 +186,6 @@
 
     /**
      * Returns video state of the primary call.
-     *  @hide
      */
     public int getVideoState() {
         return VideoProfile.VideoState.AUDIO_ONLY;
@@ -373,7 +371,6 @@
      * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @param videoState The new video state.
-     * @hide
      */
     public final void setVideoState(Connection c, int videoState) {
         Log.d(this, "setVideoState Conference: %s Connection: %s VideoState: %s",
@@ -387,7 +384,6 @@
      * Sets the video connection provider.
      *
      * @param videoProvider The video provider.
-     * @hide
      */
     public final void setVideoProvider(Connection c, Connection.VideoProvider videoProvider) {
         Log.d(this, "setVideoProvider Conference: %s Connection: %s VideoState: %s",
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4bc639b..0bf9118 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -106,38 +106,32 @@
 
     /**
      * Local device supports receiving video.
-     * @hide
      */
     public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
 
     /**
      * Local device supports transmitting video.
-     * @hide
      */
     public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
 
     /**
      * Local device supports bidirectional video calling.
-     * @hide
      */
     public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
             CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
 
     /**
      * Remote device supports receiving video.
-     * @hide
      */
     public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
 
     /**
      * Remote device supports transmitting video.
-     * @hide
      */
     public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
 
     /**
      * Remote device supports bidirectional video calling.
-     * @hide
      */
     public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
             CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
@@ -187,14 +181,12 @@
 
     /**
      * Call can be upgraded to a video call.
-     * @hide
      */
     public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
 
     /**
      * For video calls, indicates whether the outgoing video for the call can be paused using
      * the {@link android.telecom.VideoProfile.VideoState#PAUSED} VideoState.
-     * @hide
      */
     public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
 
@@ -1041,7 +1033,6 @@
      * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @param videoState The new video state.
-     * @hide
      */
     public final void setVideoState(int videoState) {
         checkImmutable();
@@ -1105,7 +1096,6 @@
     /**
      * Sets the video connection provider.
      * @param videoProvider The video provider.
-     * @hide
      */
     public final void setVideoProvider(VideoProvider videoProvider) {
         checkImmutable();
@@ -1414,7 +1404,6 @@
      * a request to accept.
      *
      * @param videoState The video state in which to answer the connection.
-     * @hide
      */
     public void onAnswer(int videoState) {}
 
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 71b481b..f5cceea 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -50,7 +50,6 @@
      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
      * @param extras Application-specific extra data.
      * @param videoState Determines the video state for the connection.
-     * @hide
      */
     public ConnectionRequest(
             PhoneAccountHandle accountHandle,
@@ -95,7 +94,6 @@
      * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @return The video state for the connection.
-     * @hide
      */
     public int getVideoState() {
         return mVideoState;
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 4185651..13eb016 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -147,7 +147,6 @@
         }
 
         @Override
-        /** @hide */
         public void answerVideo(String callId, int videoState) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index fd0c06d..d3df151 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -20,6 +20,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.net.Uri;
 import android.provider.Settings;
 import android.text.TextUtils;
 
@@ -151,14 +152,14 @@
 
         for (ResolveInfo resolveInfo : resolveInfoList) {
             final ActivityInfo activityInfo = resolveInfo.activityInfo;
-            if (activityInfo == null) {
-                continue;
+            if (activityInfo != null && !packageNames.contains(activityInfo.packageName)) {
+                packageNames.add(activityInfo.packageName);
             }
-            packageNames.add(activityInfo.packageName);
         }
 
-        // TODO: Filter for apps that don't handle DIAL intent with tel scheme
-        return packageNames;
+        final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
+        dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
+        return filterByIntent(context, packageNames, dialIntentWithTelScheme);
     }
 
     /**
@@ -182,6 +183,36 @@
                 || packageName.equals(tm.getSystemDialerPackage());
     }
 
+    /**
+     * Filter a given list of package names for those packages that contain an activity that has
+     * an intent filter for a given intent.
+     *
+     * @param context A valid context
+     * @param packageNames List of package names to filter.
+     * @return The filtered list.
+     */
+    private static List<String> filterByIntent(Context context, List<String> packageNames,
+            Intent intent) {
+        if (packageNames == null || packageNames.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        final List<String> result = new ArrayList<>();
+        final List<ResolveInfo> resolveInfoList =
+                context.getPackageManager().queryIntentActivities(intent, 0);
+        final int length = resolveInfoList.size();
+        for (int i = 0; i < length; i++) {
+            final ActivityInfo info = resolveInfoList.get(i).activityInfo;
+            if (info != null && packageNames.contains(info.packageName)
+                    && !result.contains(info.packageName)) {
+                result.add(info.packageName);
+            }
+        }
+
+        return result;
+    }
+
+
     private static TelecomManager getTelecomManager(Context context) {
         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
     }
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
index dd823ae..b54f9be 100644
--- a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -30,6 +30,7 @@
 
 import junit.framework.Assert;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
@@ -102,7 +103,11 @@
             // otherwise raise an
             // exception with the first error encountered.
             assertNull(getStackTrace(err), err);
-            assertTrue("App crashed after launch.", processStillUp(packageName));
+            try {
+                assertTrue("App crashed after launch.", processStillUp(packageName));
+            } finally {
+                returnHome();
+            }
         } else {
             Log.d(TAG, "Missing argument, use " + PACKAGE_TO_LAUNCH +
                     " to specify the package to launch");
@@ -138,6 +143,19 @@
         }
     }
 
+    private void returnHome() {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        // Send the "home" intent and wait 2 seconds for us to get there
+        mContext.startActivity(homeIntent);
+        try {
+            Thread.sleep(mWorkspaceLaunchTimeout);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
     /**
      * Launches and activity and queries for errors.
      *
@@ -150,9 +168,6 @@
         // the recommended way to see if this is a tv or not.
         boolean isleanback = !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
             && !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
-        homeIntent.addCategory(Intent.CATEGORY_HOME);
-        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         Intent intent;
         if (isleanback) {
             Log.d(TAG, "Leanback and relax! " + packageName);
@@ -173,14 +188,6 @@
             // ignore
         }
 
-        // Send the "home" intent and wait 2 seconds for us to get there
-        mContext.startActivity(homeIntent);
-        try {
-            Thread.sleep(mWorkspaceLaunchTimeout);
-        } catch (InterruptedException e) {
-            // ignore
-        }
-
         // See if there are any errors. We wait until down here to give ANRs as
         // much time as
         // possible to occur.
@@ -198,6 +205,12 @@
         return null;
     }
 
+    private boolean ensureForegroundActivity(RunningAppProcessInfo info) {
+        Log.d(TAG, String.format("ensureForegroundActivity: proc=%s, pid=%d, state=%d",
+                info.processName, info.pid, info.processState));
+        return info.processState == ActivityManager.PROCESS_STATE_TOP;
+    }
+
     /**
      * Determine if a given package is still running.
      *
@@ -207,19 +220,32 @@
     private boolean processStillUp(String packageName) {
         String processName = getProcessName(packageName);
         List<RunningAppProcessInfo> runningApps = mActivityManager.getRunningAppProcesses();
+        List<RunningAppProcessInfo> relatedProcs = new ArrayList<>();
         for (RunningAppProcessInfo app : runningApps) {
             if (app.processName.equalsIgnoreCase(processName)) {
-                Log.d(TAG, "Found process " + app.processName);
+                if (!ensureForegroundActivity(app)) {
+                    Log.w(TAG, "Found process but it's not top activity.");
+                    return false;
+                }
                 return true;
             }
             for (String relatedPackage : app.pkgList) {
-                if (relatedPackage.equalsIgnoreCase(processName)) {
-                    Log.d(TAG, "Found process " + app.processName);
-                    return true;
+                if (relatedPackage.equalsIgnoreCase(packageName)) {
+                    relatedProcs.add(app);
                 }
             }
         }
-        Log.d(TAG, "Failed to find process " + processName + " with package name "
+        // now that we are here, we've found no RAPI's directly matching processName, but
+        // potentially a List of them with one of related packages being processName
+        if (!relatedProcs.isEmpty()) {
+            for (RunningAppProcessInfo app : relatedProcs) {
+                if (ensureForegroundActivity(app)) {
+                    return true;
+                }
+            }
+            Log.w(TAG, "Found related processes, but none has top activity.");
+        }
+        Log.w(TAG, "Failed to find process " + processName + " with package name "
                 + packageName);
         return false;
     }
diff --git a/tests/HierarchyViewerTest/.gitignore b/tests/HierarchyViewerTest/.gitignore
new file mode 100644
index 0000000..75eec98
--- /dev/null
+++ b/tests/HierarchyViewerTest/.gitignore
@@ -0,0 +1,6 @@
+.gradle
+.idea
+*.iml
+gradle*
+build
+local.properties
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
new file mode 100644
index 0000000..07b90f0
--- /dev/null
+++ b/tests/HierarchyViewerTest/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := HierarchyViewerTest
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+include $(BUILD_PACKAGE)
diff --git a/tests/HierarchyViewerTest/AndroidManifest.xml b/tests/HierarchyViewerTest/AndroidManifest.xml
new file mode 100644
index 0000000..65f2fd3
--- /dev/null
+++ b/tests/HierarchyViewerTest/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<!--
+  ~ 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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.test.hierarchyviewer">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name=".MainActivity"
+            android:label="HvTest" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.test.hierarchyviewer" />
+</manifest>
diff --git a/tests/HierarchyViewerTest/build.gradle b/tests/HierarchyViewerTest/build.gradle
new file mode 100644
index 0000000..e8cdfa2
--- /dev/null
+++ b/tests/HierarchyViewerTest/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.1.0+'
+
+    }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 21
+    buildToolsVersion "22.0.0"
+
+    defaultConfig {
+        minSdkVersion 21
+        targetSdkVersion 21
+        versionCode 1
+        versionName "1.0"
+    }
+
+    sourceSets {
+	main {
+	    manifest.srcFile 'AndroidManifest.xml'
+	    java.srcDirs = ['src']
+	    res.srcDirs = ['res']
+	}
+    }
+}
diff --git a/tests/HierarchyViewerTest/res/layout/activity_main.xml b/tests/HierarchyViewerTest/res/layout/activity_main.xml
new file mode 100644
index 0000000..410a776
--- /dev/null
+++ b/tests/HierarchyViewerTest/res/layout/activity_main.xml
@@ -0,0 +1,12 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/textView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:scaleX="10"
+        android:text="@string/test" />
+
+</RelativeLayout>
diff --git a/tests/HierarchyViewerTest/res/menu/menu_main.xml b/tests/HierarchyViewerTest/res/menu/menu_main.xml
new file mode 100644
index 0000000..9b78a1e
--- /dev/null
+++ b/tests/HierarchyViewerTest/res/menu/menu_main.xml
@@ -0,0 +1,5 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
+    <item android:id="@+id/action_settings" android:title="Settings"
+        android:orderInCategory="100" android:showAsAction="never" />
+</menu>
diff --git a/tests/HierarchyViewerTest/res/values/strings.xml b/tests/HierarchyViewerTest/res/values/strings.xml
new file mode 100644
index 0000000..800ee1c
--- /dev/null
+++ b/tests/HierarchyViewerTest/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="test">Hello World</string>
+</resources>
\ No newline at end of file
diff --git a/tests/HierarchyViewerTest/run_tests.sh b/tests/HierarchyViewerTest/run_tests.sh
new file mode 100644
index 0000000..094bb4c
--- /dev/null
+++ b/tests/HierarchyViewerTest/run_tests.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+# Runs the tests in this apk
+adb install $OUT/data/app/HierarchyViewerTest/HierarchyViewerTest.apk
+adb shell am instrument -w com.android.test.hierarchyviewer/android.test.InstrumentationTestRunner
diff --git a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/Decoder.java b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/Decoder.java
new file mode 100644
index 0000000..c6f1470
--- /dev/null
+++ b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/Decoder.java
@@ -0,0 +1,101 @@
+package com.android.test.hierarchyviewer;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Decoder {
+    // Prefixes for simple primitives. These match the JNI definitions.
+    public static final byte SIG_BOOLEAN = 'Z';
+    public static final byte SIG_BYTE = 'B';
+    public static final byte SIG_SHORT = 'S';
+    public static final byte SIG_INT = 'I';
+    public static final byte SIG_LONG = 'J';
+    public static final byte SIG_FLOAT = 'F';
+    public static final byte SIG_DOUBLE = 'D';
+
+    // Prefixes for some commonly used objects
+    public static final byte SIG_STRING = 'R';
+
+    public static final byte SIG_MAP = 'M'; // a map with an short key
+    public static final short SIG_END_MAP = 0;
+
+    private final ByteBuffer mBuf;
+
+    public Decoder(byte[] buf) {
+        this(ByteBuffer.wrap(buf));
+    }
+
+    public Decoder(ByteBuffer buf) {
+        mBuf = buf;
+    }
+
+    public boolean hasRemaining() {
+        return mBuf.hasRemaining();
+    }
+
+    public Object readObject() {
+        byte sig = mBuf.get();
+
+        switch (sig) {
+            case SIG_BOOLEAN:
+                return mBuf.get() == 0 ? Boolean.FALSE : Boolean.TRUE;
+            case SIG_BYTE:
+                return mBuf.get();
+            case SIG_SHORT:
+                return mBuf.getShort();
+            case SIG_INT:
+                return mBuf.getInt();
+            case SIG_LONG:
+                return mBuf.getLong();
+            case SIG_FLOAT:
+                return mBuf.getFloat();
+            case SIG_DOUBLE:
+                return mBuf.getDouble();
+            case SIG_STRING:
+                return readString();
+            case SIG_MAP:
+                return readMap();
+            default:
+                throw new DecoderException(sig, mBuf.position() - 1);
+        }
+    }
+
+    private String readString() {
+        short len = mBuf.getShort();
+        byte[] b = new byte[len];
+        mBuf.get(b, 0, len);
+        return new String(b, Charset.forName("utf-8"));
+    }
+
+    private Map<Short, Object> readMap() {
+        Map<Short, Object> m = new HashMap<Short, Object>();
+
+        while (true) {
+            Object o = readObject();
+            if (!(o instanceof Short)) {
+                throw new DecoderException("Expected short key, got " + o.getClass());
+            }
+
+            Short key = (Short)o;
+            if (key == SIG_END_MAP) {
+                break;
+            }
+
+            m.put(key, readObject());
+        }
+
+        return m;
+    }
+
+    public static class DecoderException extends RuntimeException {
+        public DecoderException(byte seen, int pos) {
+            super(String.format("Unexpected byte %c seen at position %d", (char)seen, pos));
+        }
+
+        public DecoderException(String msg) {
+            super(msg);
+        }
+    }
+}
diff --git a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/MainActivity.java b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/MainActivity.java
new file mode 100644
index 0000000..3a67273
--- /dev/null
+++ b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/MainActivity.java
@@ -0,0 +1,44 @@
+package com.android.test.hierarchyviewer;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+
+public class MainActivity extends Activity {
+    private static final String TAG = "Main";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        View textView = findViewById(R.id.textView);
+        Log.d(TAG, "x, y = " + textView.getX() + ", " + textView.getY());
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Inflate the menu; this adds items to the action bar if it is present.
+        getMenuInflater().inflate(R.menu.menu_main, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle action bar item clicks here. The action bar will
+        // automatically handle clicks on the Home/Up button, so long
+        // as you specify a parent activity in AndroidManifest.xml.
+        int id = item.getItemId();
+
+        //noinspection SimplifiableIfStatement
+        if (id == R.id.action_settings) {
+            return true;
+        }
+
+        return super.onOptionsItemSelected(item);
+    }
+}
diff --git a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/MainActivityTest.java b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/MainActivityTest.java
new file mode 100644
index 0000000..ea3710d
--- /dev/null
+++ b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/MainActivityTest.java
@@ -0,0 +1,81 @@
+package com.android.test.hierarchyviewer;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
+
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
+    private MainActivity mActivity;
+    private View mTextView;
+
+
+    public MainActivityTest() {
+        super(MainActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mTextView = mActivity.findViewById(R.id.textView);
+    }
+
+    private byte[] encode(View view) throws ClassNotFoundException, NoSuchMethodException,
+            IllegalAccessException, InstantiationException, InvocationTargetException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024 * 1024);
+
+        Object encoder = createEncoder(baos);
+        invokeMethod(View.class, view, "encode", encoder);
+        invokeMethod(encoder.getClass(), encoder, "endStream");
+
+        return baos.toByteArray();
+    }
+
+    private Object invokeMethod(Class targetClass, Object target, String methodName, Object... params)
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Class[] paramClasses = new Class[params.length];
+        for (int i = 0; i < params.length; i++) {
+            paramClasses[i] = params[i].getClass();
+        }
+        Method method = targetClass.getDeclaredMethod(methodName, paramClasses);
+        method.setAccessible(true);
+        return method.invoke(target, params);
+    }
+
+    private Object createEncoder(ByteArrayOutputStream baos) throws ClassNotFoundException,
+            NoSuchMethodException, IllegalAccessException, InvocationTargetException,
+            InstantiationException {
+        Class clazz = Class.forName("android.view.ViewHierarchyEncoder");
+        Constructor constructor = clazz.getConstructor(ByteArrayOutputStream.class);
+        return constructor.newInstance(baos);
+    }
+
+    public void testTextView() throws Exception {
+        byte[] data = encode(mTextView);
+        assertNotNull(data);
+        assertTrue(data.length > 0);
+
+        ViewDumpParser parser = new ViewDumpParser();
+        parser.parse(data);
+
+        List<Map<Short, Object>> views = parser.getViews();
+        Map<String, Short> propertyNameTable = parser.getIds();
+
+        assertEquals(1, views.size());
+        assertNotNull(propertyNameTable);
+
+        Map<Short, Object> textViewProperties = views.get(0);
+        assertEquals("android.widget.TextView",
+                textViewProperties.get(propertyNameTable.get("meta:__name__")));
+
+        assertEquals(mActivity.getString(R.string.test),
+                textViewProperties.get(propertyNameTable.get("text:text")));
+    }
+}
diff --git a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
new file mode 100644
index 0000000..0111bc6
--- /dev/null
+++ b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
@@ -0,0 +1,73 @@
+package com.android.test.hierarchyviewer;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class ViewDumpParser {
+    private Map<String, Short> mIds;
+    private List<Map<Short,Object>> mViews;
+
+    public void parse(byte[] data) {
+        Decoder d = new Decoder(ByteBuffer.wrap(data));
+
+        mViews = new ArrayList<>(100);
+        while (d.hasRemaining()) {
+            Object o = d.readObject();
+            if (o instanceof Map) {
+                //noinspection unchecked
+                mViews.add((Map<Short, Object>) o);
+            }
+        }
+
+        if (mViews.isEmpty()) {
+            return;
+        }
+
+        // the last one is the property map
+        Map<Short,Object> idMap = mViews.remove(mViews.size() - 1);
+        mIds = reverse(idMap);
+    }
+
+    public String getFirstView() {
+        if (mViews.isEmpty()) {
+            return null;
+        }
+
+        Map<Short, Object> props = mViews.get(0);
+        Object name = getProperty(props, "__name__");
+        Object hash = getProperty(props, "__hash__");
+
+        if (name instanceof String && hash instanceof Integer) {
+            return String.format(Locale.US, "%s@%x", name, hash);
+        } else {
+            return null;
+        }
+    }
+
+    private Object getProperty(Map<Short, Object> props, String key) {
+        return props.get(mIds.get(key));
+    }
+
+    private static Map<String, Short> reverse(Map<Short, Object> m) {
+        Map<String, Short> r = new HashMap<String, Short>(m.size());
+
+        for (Map.Entry<Short, Object> e : m.entrySet()) {
+            r.put((String)e.getValue(), e.getKey());
+        }
+
+        return r;
+    }
+
+    public List<Map<Short, Object>> getViews() {
+        return mViews;
+    }
+
+    public Map<String, Short> getIds() {
+        return mIds;
+    }
+
+}
diff --git a/tests/VoiceInteraction/res/layout/main.xml b/tests/VoiceInteraction/res/layout/main.xml
index 34a7563..092d37d 100644
--- a/tests/VoiceInteraction/res/layout/main.xml
+++ b/tests/VoiceInteraction/res/layout/main.xml
@@ -34,12 +34,6 @@
             android:text="@string/asyncStructure"
             />
 
-    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
-        android:assistBlocked="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:text="This won't be included in assist."
-        />
-
 </LinearLayout>
 
 
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java
index 73e04e5..ae8e9e4 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java
@@ -20,7 +20,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewAssistStructure;
+import android.view.ViewStructure;
 import android.widget.TextView;
 
 /**
@@ -32,9 +32,9 @@
     }
 
     @Override
-    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
+    public void onProvideVirtualStructure(ViewStructure structure) {
         structure.setChildCount(1);
-        final ViewAssistStructure child = structure.asyncNewChild(0);
+        final ViewStructure child = structure.asyncNewChild(0);
         final int width = getWidth();
         final int height = getHeight();
         (new Thread() {
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index 4bd83e9..41d94b7 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -27,6 +27,7 @@
 
 import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.Theme;
+import android.content.res.Resources.ThemeKey;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 
@@ -110,22 +111,16 @@
     private static boolean setupResources(Theme thisTheme) {
         // Key is a space-separated list of theme ids applied that have been merged into the
         // BridgeContext's theme to make thisTheme.
-        String[] appliedStyles = thisTheme.getKey().split(" ");
+        final ThemeKey key = thisTheme.getKey();
+        final int[] resId = key.mResId;
+        final boolean[] force = key.mForce;
+
         boolean changed = false;
-        for (String s : appliedStyles) {
-            if (s.isEmpty()) {
-                continue;
-            }
-            // See the definition of force parameter in Theme.applyStyle().
-            boolean force = false;
-            if (s.charAt(s.length() - 1) == '!') {
-                force = true;
-                s = s.substring(0, s.length() - 1);
-            }
-            int styleId = Integer.parseInt(s, 16);
-            StyleResourceValue style = resolveStyle(styleId);
+        for (int i = 0, N = key.mCount; i < N; i++) {
+            StyleResourceValue style = resolveStyle(resId[i]);
             if (style != null) {
-                RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(style, force);
+                RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(
+                        style, force[i]);
                 changed = true;
             }