Merge "Camera2: Remove spurious warnings" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 3edaefc..35bb66c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -325,8 +325,6 @@
 	media/java/android/media/IRemoteVolumeObserver.aidl \
 	media/java/android/media/IRingtonePlayer.aidl \
 	media/java/android/media/IVolumeController.aidl \
-	media/java/android/media/browse/IMediaBrowserService.aidl \
-	media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl \
 	media/java/android/media/projection/IMediaProjection.aidl \
 	media/java/android/media/projection/IMediaProjectionCallback.aidl \
 	media/java/android/media/projection/IMediaProjectionManager.aidl \
@@ -346,6 +344,8 @@
 	media/java/android/media/tv/ITvInputServiceCallback.aidl \
 	media/java/android/media/tv/ITvInputSession.aidl \
 	media/java/android/media/tv/ITvInputSessionCallback.aidl \
+	media/java/android/service/media/IMediaBrowserService.aidl \
+	media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl \
 	telecomm/java/com/android/internal/telecomm/IVideoCallback.aidl \
 	telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl \
 	telecomm/java/com/android/internal/telecomm/IConnectionService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 8236f38..6815ba1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -309,7 +309,6 @@
     field public static final int addStatesFromChildren = 16842992; // 0x10100f0
     field public static final int adjustViewBounds = 16843038; // 0x101011e
     field public static final int advancedPrintOptionsActivity = 16843761; // 0x10103f1
-    field public static final int ageHint = 16843962; // 0x10104ba
     field public static final int alertDialogIcon = 16843605; // 0x1010355
     field public static final int alertDialogStyle = 16842845; // 0x101005d
     field public static final int alertDialogTheme = 16843529; // 0x1010309
@@ -459,6 +458,7 @@
     field public static final int configure = 16843357; // 0x101025d
     field public static final int constantSize = 16843158; // 0x1010196
     field public static final int content = 16843355; // 0x101025b
+    field public static final int contentAgeHint = 16843962; // 0x10104ba
     field public static final int contentAuthority = 16843408; // 0x1010290
     field public static final int contentDescription = 16843379; // 0x1010273
     field public static final int contentInsetEnd = 16843860; // 0x1010454
@@ -905,6 +905,8 @@
     field public static final int multiprocess = 16842771; // 0x1010013
     field public static final int name = 16842755; // 0x1010003
     field public static final int navigationBarColor = 16843858; // 0x1010452
+    field public static final int navigationContentDescription = 16843970; // 0x10104c2
+    field public static final int navigationIcon = 16843969; // 0x10104c1
     field public static final int navigationMode = 16843471; // 0x10102cf
     field public static final int negativeButtonText = 16843254; // 0x10101f6
     field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
@@ -1360,7 +1362,6 @@
     field public static final int trimPathEnd = 16843811; // 0x1010423
     field public static final int trimPathOffset = 16843812; // 0x1010424
     field public static final int trimPathStart = 16843810; // 0x1010422
-    field public static final int tvContentRatingDescription = 16843955; // 0x10104b3
     field public static final int type = 16843169; // 0x10101a1
     field public static final int typeface = 16842902; // 0x1010096
     field public static final int uiOptions = 16843672; // 0x1010398
@@ -2026,6 +2027,12 @@
     field public static final int TextAppearance_Material_Medium = 16974355; // 0x1030213
     field public static final int TextAppearance_Material_Medium_Inverse = 16974356; // 0x1030214
     field public static final int TextAppearance_Material_Menu = 16974554; // 0x10302da
+    field public static final int TextAppearance_Material_Notification = 16974560; // 0x10302e0
+    field public static final int TextAppearance_Material_Notification_Emphasis = 16974565; // 0x10302e5
+    field public static final int TextAppearance_Material_Notification_Info = 16974563; // 0x10302e3
+    field public static final int TextAppearance_Material_Notification_Line2 = 16974562; // 0x10302e2
+    field public static final int TextAppearance_Material_Notification_Time = 16974564; // 0x10302e4
+    field public static final int TextAppearance_Material_Notification_Title = 16974561; // 0x10302e1
     field public static final int TextAppearance_Material_SearchResult_Subtitle = 16974357; // 0x1030215
     field public static final int TextAppearance_Material_SearchResult_Title = 16974358; // 0x1030216
     field public static final int TextAppearance_Material_Small = 16974359; // 0x1030217
@@ -2064,13 +2071,6 @@
     field public static final int TextAppearance_StatusBar_EventContent = 16973927; // 0x1030067
     field public static final int TextAppearance_StatusBar_EventContent_Title = 16973928; // 0x1030068
     field public static final int TextAppearance_StatusBar_Icon = 16973926; // 0x1030066
-    field public static final int TextAppearance_StatusBar_Material = 16974559; // 0x10302df
-    field public static final int TextAppearance_StatusBar_Material_EventContent = 16974560; // 0x10302e0
-    field public static final int TextAppearance_StatusBar_Material_EventContent_Emphasis = 16974565; // 0x10302e5
-    field public static final int TextAppearance_StatusBar_Material_EventContent_Info = 16974563; // 0x10302e3
-    field public static final int TextAppearance_StatusBar_Material_EventContent_Line2 = 16974562; // 0x10302e2
-    field public static final int TextAppearance_StatusBar_Material_EventContent_Time = 16974564; // 0x10302e4
-    field public static final int TextAppearance_StatusBar_Material_EventContent_Title = 16974561; // 0x10302e1
     field public static final int TextAppearance_StatusBar_Title = 16973925; // 0x1030065
     field public static final int TextAppearance_SuggestionHighlight = 16974104; // 0x1030118
     field public static final int TextAppearance_Theme = 16973888; // 0x1030040
@@ -2166,18 +2166,22 @@
     field public static final int Theme_Material_Dialog = 16974386; // 0x1030232
     field public static final int Theme_Material_DialogWhenLarge = 16974390; // 0x1030236
     field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974391; // 0x1030237
+    field public static final int Theme_Material_Dialog_Alert = 16974570; // 0x10302ea
     field public static final int Theme_Material_Dialog_MinWidth = 16974387; // 0x1030233
     field public static final int Theme_Material_Dialog_NoActionBar = 16974388; // 0x1030234
     field public static final int Theme_Material_Dialog_NoActionBar_MinWidth = 16974389; // 0x1030235
+    field public static final int Theme_Material_Dialog_Presentation = 16974571; // 0x10302eb
     field public static final int Theme_Material_InputMethod = 16974392; // 0x1030238
     field public static final int Theme_Material_Light = 16974402; // 0x1030242
     field public static final int Theme_Material_Light_DarkActionBar = 16974403; // 0x1030243
     field public static final int Theme_Material_Light_Dialog = 16974404; // 0x1030244
     field public static final int Theme_Material_Light_DialogWhenLarge = 16974408; // 0x1030248
     field public static final int Theme_Material_Light_DialogWhenLarge_NoActionBar = 16974409; // 0x1030249
+    field public static final int Theme_Material_Light_Dialog_Alert = 16974572; // 0x10302ec
     field public static final int Theme_Material_Light_Dialog_MinWidth = 16974405; // 0x1030245
     field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974406; // 0x1030246
     field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974407; // 0x1030247
+    field public static final int Theme_Material_Light_Dialog_Presentation = 16974573; // 0x10302ed
     field public static final int Theme_Material_Light_NoActionBar = 16974410; // 0x103024a
     field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974411; // 0x103024b
     field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974412; // 0x103024c
@@ -2566,7 +2570,7 @@
     field public static final int Widget_Material_Light_SeekBar = 16974534; // 0x10302c6
     field public static final int Widget_Material_Light_SegmentedButton = 16974535; // 0x10302c7
     field public static final int Widget_Material_Light_Spinner = 16974537; // 0x10302c9
-    field public static final int Widget_Material_Light_Spinner_Form = 16974567; // 0x10302e7
+    field public static final int Widget_Material_Light_Spinner_Underlined = 16974567; // 0x10302e7
     field public static final int Widget_Material_Light_StackView = 16974536; // 0x10302c8
     field public static final int Widget_Material_Light_Tab = 16974538; // 0x10302ca
     field public static final int Widget_Material_Light_TabWidget = 16974539; // 0x10302cb
@@ -2593,7 +2597,7 @@
     field public static final int Widget_Material_SeekBar = 16974471; // 0x1030287
     field public static final int Widget_Material_SegmentedButton = 16974472; // 0x1030288
     field public static final int Widget_Material_Spinner = 16974474; // 0x103028a
-    field public static final int Widget_Material_Spinner_Form = 16974566; // 0x10302e6
+    field public static final int Widget_Material_Spinner_Underlined = 16974566; // 0x10302e6
     field public static final int Widget_Material_StackView = 16974473; // 0x1030289
     field public static final int Widget_Material_Tab = 16974475; // 0x103028b
     field public static final int Widget_Material_TabWidget = 16974476; // 0x103028c
@@ -2625,6 +2629,7 @@
     field public static final int Widget_Toolbar = 16974339; // 0x1030203
     field public static final int Widget_Toolbar_Button_Navigation = 16974340; // 0x1030204
     field public static final int Widget_WebView = 16973875; // 0x1030033
+    field public static final int __removed = 16974559; // 0x10302df
     field public static final int l_resource_pad1 = 16974336; // 0x1030200
     field public static final int l_resource_pad10 = 16974327; // 0x10301f7
     field public static final int l_resource_pad11 = 16974326; // 0x10301f6
@@ -3509,7 +3514,7 @@
     method public void onTrimMemory(int);
     method public void onUserInteraction();
     method protected void onUserLeaveHint();
-    method public void onVisibleBehindCancelled();
+    method public void onVisibleBehindCanceled();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
@@ -3604,8 +3609,7 @@
     method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap);
     method public boolean clearApplicationUserData();
     method public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
-    method public int getAppTaskThumbnailHeight();
-    method public int getAppTaskThumbnailWidth();
+    method public android.util.Size getAppTaskThumbnailSize();
     method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks();
     method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
     method public int getLargeMemoryClass();
@@ -4506,8 +4510,8 @@
   }
 
   public class KeyguardManager {
+    method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
     method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
-    method public android.content.Intent getConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
     method public boolean inKeyguardRestrictedInputMode();
     method public boolean isKeyguardLocked();
     method public boolean isKeyguardSecure();
@@ -5424,6 +5428,7 @@
     method public java.lang.String[] getAccountTypesWithManagementDisabled();
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
+    method public boolean getAutoTimeRequired();
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
@@ -5449,8 +5454,6 @@
     method public boolean getScreenCaptureDisabled(android.content.ComponentName);
     method public boolean getStorageEncryption(android.content.ComponentName);
     method public int getStorageEncryptionStatus();
-    method public java.util.List<java.lang.String> getTrustAgentFeaturesEnabled(android.content.ComponentName, android.content.ComponentName);
-    method public boolean getUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public boolean hasCaCertInstalled(byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -5461,6 +5464,7 @@
     method public boolean isLockTaskPermitted(java.lang.String);
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
+    method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void removeActiveAdmin(android.content.ComponentName);
     method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -5469,6 +5473,7 @@
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
+    method public void setAutoTimeRequired(android.content.ComponentName, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
@@ -5496,7 +5501,6 @@
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
-    method public void setTrustAgentFeaturesEnabled(android.content.ComponentName, android.content.ComponentName, java.util.List<java.lang.String>);
     method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
     method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
     method public void uninstallAllUserCaCerts(android.content.ComponentName);
@@ -7145,6 +7149,7 @@
     field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+    field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
     field public static final java.lang.String SCHEME_CONTENT = "content";
     field public static final java.lang.String SCHEME_FILE = "file";
@@ -8890,6 +8895,7 @@
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
     field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+    field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
     field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
     field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
     field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
@@ -14522,7 +14528,6 @@
     method public abstract long getTimestamp();
     method public abstract int getWidth();
     method public void setCropRect(android.graphics.Rect);
-    field protected android.graphics.Rect mCropRect;
   }
 
   public static abstract class Image.Plane {
@@ -14654,7 +14659,6 @@
   }
 
   public static final class MediaCodec.CodecException extends java.lang.IllegalStateException {
-    ctor public MediaCodec.CodecException(int, int, java.lang.String);
     method public int getErrorCode();
     method public boolean isRecoverable();
     method public boolean isTransient();
@@ -14686,14 +14690,22 @@
     method public final boolean isEncoder();
   }
 
+  public static final class MediaCodecInfo.AudioCapabilities {
+    method public android.util.Range<java.lang.Integer> getBitrateRange();
+    method public int getMaxInputChannelCount();
+    method public android.util.Range<java.lang.Integer>[] getSupportedSampleRateRanges();
+    method public int[] getSupportedSampleRates();
+    method public boolean isSampleRateSupported(int);
+  }
+
   public static final class MediaCodecInfo.CodecCapabilities {
     ctor public MediaCodecInfo.CodecCapabilities();
-    method public static final android.media.MediaCodecInfo.CodecCapabilities CreateFromProfileLevel(java.lang.String, int, int);
-    method public final android.media.MediaCodecInfo.CodecCapabilities.AudioCapabilities getAudioCapabilities();
-    method public final android.media.MediaFormat getDefaultFormat();
-    method public final android.media.MediaCodecInfo.CodecCapabilities.EncoderCapabilities getEncoderCapabilities();
-    method public final java.lang.String getMime();
-    method public final android.media.MediaCodecInfo.CodecCapabilities.VideoCapabilities getVideoCapabilities();
+    method public static android.media.MediaCodecInfo.CodecCapabilities CreateFromProfileLevel(java.lang.String, int, int);
+    method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
+    method public android.media.MediaFormat getDefaultFormat();
+    method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
+    method public java.lang.String getMimeType();
+    method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
     method public final boolean isFeatureRequired(java.lang.String);
     method public final boolean isFeatureSupported(java.lang.String);
     method public final boolean isFormatSupported(android.media.MediaFormat);
@@ -14751,39 +14763,6 @@
     field public android.media.MediaCodecInfo.CodecProfileLevel[] profileLevels;
   }
 
-  public static final class MediaCodecInfo.CodecCapabilities.AudioCapabilities extends android.media.MediaCodecInfo.CodecCapabilities.BaseCapabilities {
-    method public final int getMaxInputChannelCount();
-    method public final android.util.Range<java.lang.Integer>[] getSupportedSampleRateRanges();
-    method public final int[] getSupportedSampleRates();
-    method public final boolean isSampleRateSupported(int);
-  }
-
-  public static class MediaCodecInfo.CodecCapabilities.BaseCapabilities {
-    method public final android.util.Range<java.lang.Integer> getBitrateRange();
-  }
-
-  public static final class MediaCodecInfo.CodecCapabilities.EncoderCapabilities {
-    method public final android.util.Range<java.lang.Integer> getComplexityRange();
-    method public final android.util.Range<java.lang.Integer> getQualityRange();
-    method public final boolean isBitrateModeSupported(int);
-    field public static final int BITRATE_MODE_CBR = 2; // 0x2
-    field public static final int BITRATE_MODE_CQ = 0; // 0x0
-    field public static final int BITRATE_MODE_VBR = 1; // 0x1
-  }
-
-  public static final class MediaCodecInfo.CodecCapabilities.VideoCapabilities extends android.media.MediaCodecInfo.CodecCapabilities.BaseCapabilities {
-    method public final boolean areSizeAndRateSupported(int, int, double);
-    method public final int getHeightAlignment();
-    method public final android.util.Range<java.lang.Integer> getSupportedFrameRates();
-    method public final android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int);
-    method public final android.util.Range<java.lang.Integer> getSupportedHeights();
-    method public final android.util.Range<java.lang.Integer> getSupportedHeightsFor(int);
-    method public final android.util.Range<java.lang.Integer> getSupportedWidths();
-    method public final android.util.Range<java.lang.Integer> getSupportedWidthsFor(int);
-    method public final int getWidthAlignment();
-    method public final boolean isSizeSupported(int, int);
-  }
-
   public static final class MediaCodecInfo.CodecProfileLevel {
     ctor public MediaCodecInfo.CodecProfileLevel();
     field public static final int AACObjectELD = 39; // 0x27
@@ -14898,12 +14877,34 @@
     field public int profile;
   }
 
+  public static final class MediaCodecInfo.EncoderCapabilities {
+    method public android.util.Range<java.lang.Integer> getComplexityRange();
+    method public boolean isBitrateModeSupported(int);
+    field public static final int BITRATE_MODE_CBR = 2; // 0x2
+    field public static final int BITRATE_MODE_CQ = 0; // 0x0
+    field public static final int BITRATE_MODE_VBR = 1; // 0x1
+  }
+
+  public static final class MediaCodecInfo.VideoCapabilities {
+    method public boolean areSizeAndRateSupported(int, int, double);
+    method public android.util.Range<java.lang.Integer> getBitrateRange();
+    method public int getHeightAlignment();
+    method public android.util.Range<java.lang.Integer> getSupportedFrameRates();
+    method public android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int);
+    method public android.util.Range<java.lang.Integer> getSupportedHeights();
+    method public android.util.Range<java.lang.Integer> getSupportedHeightsFor(int);
+    method public android.util.Range<java.lang.Integer> getSupportedWidths();
+    method public android.util.Range<java.lang.Integer> getSupportedWidthsFor(int);
+    method public int getWidthAlignment();
+    method public boolean isSizeSupported(int, int);
+  }
+
   public final class MediaCodecList {
     ctor public MediaCodecList(int);
     method public final java.lang.String findDecoderForFormat(android.media.MediaFormat);
     method public final java.lang.String findEncoderForFormat(android.media.MediaFormat);
-    method public static final int getCodecCount();
-    method public static final android.media.MediaCodecInfo getCodecInfoAt(int);
+    method public static final deprecated int getCodecCount();
+    method public static final deprecated android.media.MediaCodecInfo getCodecInfoAt(int);
     method public final android.media.MediaCodecInfo[] getCodecInfos();
     field public static final int ALL_CODECS = 1; // 0x1
     field public static final int REGULAR_CODECS = 0; // 0x0
@@ -14920,6 +14921,31 @@
     ctor public MediaCryptoException(java.lang.String);
   }
 
+  public class MediaDescription implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.CharSequence getDescription();
+    method public android.os.Bundle getExtras();
+    method public android.graphics.Bitmap getIconBitmap();
+    method public android.net.Uri getIconUri();
+    method public java.lang.String getMediaId();
+    method public java.lang.CharSequence getSubtitle();
+    method public java.lang.CharSequence getTitle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class MediaDescription.Builder {
+    ctor public MediaDescription.Builder();
+    method public android.media.MediaDescription build();
+    method public android.media.MediaDescription.Builder setDescription(java.lang.CharSequence);
+    method public android.media.MediaDescription.Builder setExtras(android.os.Bundle);
+    method public android.media.MediaDescription.Builder setIconBitmap(android.graphics.Bitmap);
+    method public android.media.MediaDescription.Builder setIconUri(android.net.Uri);
+    method public android.media.MediaDescription.Builder setMediaId(java.lang.String);
+    method public android.media.MediaDescription.Builder setSubtitle(java.lang.CharSequence);
+    method public android.media.MediaDescription.Builder setTitle(java.lang.CharSequence);
+  }
+
   public final class MediaDrm {
     ctor public MediaDrm(java.util.UUID) throws android.media.UnsupportedSchemeException;
     method public void closeSession(byte[]);
@@ -15022,11 +15048,13 @@
     method public static final android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String);
     method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
     method public final java.nio.ByteBuffer getByteBuffer(java.lang.String);
+    method public boolean getFeatureEnabled(java.lang.String);
     method public final float getFloat(java.lang.String);
     method public final int getInteger(java.lang.String);
     method public final long getLong(java.lang.String);
     method public final java.lang.String getString(java.lang.String);
     method public final void setByteBuffer(java.lang.String, java.nio.ByteBuffer);
+    method public void setFeatureEnabled(java.lang.String, boolean);
     method public final void setFloat(java.lang.String, float);
     method public final void setInteger(java.lang.String, int);
     method public final void setLong(java.lang.String, long);
@@ -15048,7 +15076,6 @@
     field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
     field public static final java.lang.String KEY_COMPLEXITY = "complexity";
     field public static final java.lang.String KEY_DURATION = "durationUs";
-    field public static final java.lang.String KEY_FEATURE_ = "feature-";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
     field public static final java.lang.String KEY_HEIGHT = "height";
@@ -15064,7 +15091,6 @@
     field public static final java.lang.String KEY_MIME = "mime";
     field public static final java.lang.String KEY_PROFILE = "profile";
     field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown";
-    field public static final java.lang.String KEY_QUALITY = "quality";
     field public static final java.lang.String KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
     field public static final java.lang.String KEY_SAMPLE_RATE = "sample-rate";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
@@ -15098,7 +15124,7 @@
     method public boolean containsKey(java.lang.String);
     method public int describeContents();
     method public android.graphics.Bitmap getBitmap(java.lang.String);
-    method public android.media.MediaMetadata.Description getDescription();
+    method public android.media.MediaDescription getDescription();
     method public long getLong(java.lang.String);
     method public android.media.Rating getRating(java.lang.String);
     method public java.lang.String getString(java.lang.String);
@@ -15126,6 +15152,7 @@
     field public static final java.lang.String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
     field public static final java.lang.String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
     field public static final java.lang.String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+    field public static final java.lang.String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
     field public static final java.lang.String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
     field public static final java.lang.String METADATA_KEY_RATING = "android.media.metadata.RATING";
     field public static final java.lang.String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
@@ -15146,14 +15173,6 @@
     method public android.media.MediaMetadata.Builder putText(java.lang.String, java.lang.CharSequence);
   }
 
-  public final class MediaMetadata.Description {
-    method public java.lang.CharSequence getDescription();
-    method public android.graphics.Bitmap getIcon();
-    method public android.net.Uri getIconUri();
-    method public java.lang.CharSequence getSubtitle();
-    method public java.lang.CharSequence getTitle();
-  }
-
   public abstract deprecated class MediaMetadataEditor {
     method public synchronized void addEditableKey(int);
     method public abstract void apply();
@@ -15704,6 +15723,7 @@
   }
 
   public class Ringtone {
+    method public android.media.AudioAttributes getAudioAttributes();
     method public deprecated int getStreamType();
     method public java.lang.String getTitle(android.content.Context);
     method public boolean isPlaying();
@@ -16239,7 +16259,6 @@
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public boolean isConnected();
-    method public void loadIcon(android.net.Uri, int, int, android.media.browse.MediaBrowser.IconCallback);
     method public void subscribe(android.net.Uri, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void unsubscribe(android.net.Uri);
   }
@@ -16251,27 +16270,12 @@
     method public void onConnectionSuspended();
   }
 
-  public static abstract class MediaBrowser.IconCallback {
-    ctor public MediaBrowser.IconCallback();
-    method public void onError(android.net.Uri);
-    method public void onIconLoaded(android.net.Uri, android.graphics.Bitmap);
-  }
-
-  public static abstract class MediaBrowser.SubscriptionCallback {
-    ctor public MediaBrowser.SubscriptionCallback();
-    method public void onChildrenLoaded(android.net.Uri, java.util.List<android.media.browse.MediaBrowserItem>);
-    method public void onError(android.net.Uri);
-  }
-
-  public final class MediaBrowserItem implements android.os.Parcelable {
+  public static class MediaBrowser.MediaItem implements android.os.Parcelable {
+    ctor public MediaBrowser.MediaItem(int, android.media.MediaDescription);
     method public int describeContents();
-    method public android.os.Bundle getExtras();
+    method public android.media.MediaDescription getDescription();
     method public int getFlags();
-    method public int getIconResourceId();
-    method public android.net.Uri getIconUri();
-    method public java.lang.CharSequence getSummary();
-    method public java.lang.CharSequence getTitle();
-    method public android.net.Uri getUri();
+    method public java.lang.String getMediaId();
     method public boolean isBrowsable();
     method public boolean isPlayable();
     method public void writeToParcel(android.os.Parcel, int);
@@ -16280,37 +16284,10 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
-  public static final class MediaBrowserItem.Builder {
-    ctor public MediaBrowserItem.Builder(android.net.Uri, int, java.lang.CharSequence);
-    method public android.media.browse.MediaBrowserItem build();
-    method public android.media.browse.MediaBrowserItem.Builder setExtras(android.os.Bundle);
-    method public android.media.browse.MediaBrowserItem.Builder setIconResourceId(int);
-    method public android.media.browse.MediaBrowserItem.Builder setIconUri(android.net.Uri);
-    method public android.media.browse.MediaBrowserItem.Builder setSummary(java.lang.CharSequence);
-  }
-
-  public abstract class MediaBrowserService extends android.app.Service {
-    ctor public MediaBrowserService();
-    method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public android.media.session.MediaSession.Token getSessionToken();
-    method public void notifyChildrenChanged(android.net.Uri);
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.media.browse.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
-    method public abstract void onLoadChildren(android.net.Uri, android.media.browse.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowserItem>>);
-    method public abstract void onLoadIcon(android.net.Uri, int, int, android.media.browse.MediaBrowserService.Result<android.graphics.Bitmap>);
-    method public void setSessionToken(android.media.session.MediaSession.Token);
-    field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
-  }
-
-  public static final class MediaBrowserService.BrowserRoot {
-    ctor public MediaBrowserService.BrowserRoot(android.net.Uri, android.os.Bundle);
-    method public android.os.Bundle getExtras();
-    method public android.net.Uri getRootUri();
-  }
-
-  public class MediaBrowserService.Result {
-    method public void detach();
-    method public void sendResult(T);
+  public static abstract class MediaBrowser.SubscriptionCallback {
+    ctor public MediaBrowser.SubscriptionCallback();
+    method public void onChildrenLoaded(android.net.Uri, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
+    method public void onError(android.net.Uri);
   }
 
 }
@@ -16405,7 +16382,7 @@
     method public java.lang.String getPackageName();
     method public android.media.session.MediaController.PlaybackInfo getPlaybackInfo();
     method public android.media.session.PlaybackState getPlaybackState();
-    method public java.util.List<android.media.session.MediaSession.Item> getQueue();
+    method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
     method public android.app.PendingIntent getSessionActivity();
@@ -16422,7 +16399,7 @@
     method public void onExtrasChanged(android.os.Bundle);
     method public void onMetadataChanged(android.media.MediaMetadata);
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
-    method public void onQueueChanged(java.util.List<android.media.session.MediaSession.Item>);
+    method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void onQueueTitleChanged(java.lang.CharSequence);
     method public void onSessionDestroyed();
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
@@ -16442,16 +16419,16 @@
     method public void fastForward();
     method public void pause();
     method public void play();
+    method public void playFromMediaId(java.lang.String, android.os.Bundle);
     method public void playFromSearch(java.lang.String, android.os.Bundle);
-    method public void playUri(android.net.Uri, android.os.Bundle);
     method public void rewind();
     method public void seekTo(long);
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
     method public void sendCustomAction(java.lang.String, android.os.Bundle);
     method public void setRating(android.media.Rating);
-    method public void skipToItem(long);
     method public void skipToNext();
     method public void skipToPrevious();
+    method public void skipToQueueItem(long);
     method public void stop();
   }
 
@@ -16472,7 +16449,7 @@
     method public void setPlaybackState(android.media.session.PlaybackState);
     method public void setPlaybackToLocal(android.media.AudioAttributes);
     method public void setPlaybackToRemote(android.media.VolumeProvider);
-    method public void setQueue(java.util.List<android.media.session.MediaSession.Item>);
+    method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void setQueueTitle(java.lang.CharSequence);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
@@ -16487,34 +16464,27 @@
     method public boolean onMediaButtonEvent(android.content.Intent);
     method public void onPause();
     method public void onPlay();
+    method public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPlayFromSearch(java.lang.String, android.os.Bundle);
-    method public void onPlayUri(android.net.Uri, android.os.Bundle);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
-    method public void onSkipToItem(long);
     method public void onSkipToNext();
     method public void onSkipToPrevious();
+    method public void onSkipToQueueItem(long);
     method public void onStop();
   }
 
-  public static final class MediaSession.Item implements android.os.Parcelable {
+  public static final class MediaSession.QueueItem implements android.os.Parcelable {
+    ctor public MediaSession.QueueItem(android.media.MediaDescription, long);
     method public int describeContents();
-    method public android.os.Bundle getExtras();
-    method public long getId();
-    method public android.media.MediaMetadata getMetadata();
-    method public android.net.Uri getUri();
+    method public android.media.MediaDescription getDescription();
+    method public long getQueueId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int UNKNOWN_ID = -1; // 0xffffffff
   }
 
-  public static final class MediaSession.Item.Builder {
-    ctor public MediaSession.Item.Builder(android.media.MediaMetadata, long, android.net.Uri);
-    method public android.media.session.MediaSession.Item build();
-    method public android.media.session.MediaSession.Item.Builder setExtras(android.os.Bundle);
-  }
-
   public static final class MediaSession.Token implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -16535,6 +16505,7 @@
   public final class PlaybackState implements android.os.Parcelable {
     method public int describeContents();
     method public long getActions();
+    method public long getActiveQueueItemId();
     method public long getBufferedPosition();
     method public java.util.List<android.media.session.PlaybackState.CustomAction> getCustomActions();
     method public java.lang.CharSequence getErrorMessage();
@@ -16546,15 +16517,15 @@
     field public static final long ACTION_FAST_FORWARD = 64L; // 0x40L
     field public static final long ACTION_PAUSE = 2L; // 0x2L
     field public static final long ACTION_PLAY = 4L; // 0x4L
+    field public static final long ACTION_PLAY_FROM_MEDIA_ID = 1024L; // 0x400L
     field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L
     field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
-    field public static final long ACTION_PLAY_URI = 1024L; // 0x400L
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
-    field public static final long ACTION_SKIP_TO_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
+    field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
@@ -16568,6 +16539,7 @@
     field public static final int STATE_REWINDING = 5; // 0x5
     field public static final int STATE_SKIPPING_TO_NEXT = 10; // 0xa
     field public static final int STATE_SKIPPING_TO_PREVIOUS = 9; // 0x9
+    field public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11; // 0xb
     field public static final int STATE_STOPPED = 1; // 0x1
   }
 
@@ -16578,7 +16550,7 @@
     method public android.media.session.PlaybackState.Builder addCustomAction(android.media.session.PlaybackState.CustomAction);
     method public android.media.session.PlaybackState build();
     method public android.media.session.PlaybackState.Builder setActions(long);
-    method public android.media.session.PlaybackState.Builder setActiveItem(long);
+    method public android.media.session.PlaybackState.Builder setActiveQueueItemId(long);
     method public android.media.session.PlaybackState.Builder setBufferedPosition(long);
     method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
     method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
@@ -16776,11 +16748,13 @@
     method public boolean isRatingBlocked(android.media.tv.TvContentRating);
     method public void registerListener(android.media.tv.TvInputManager.TvInputListener, android.os.Handler);
     method public void unregisterListener(android.media.tv.TvInputManager.TvInputListener);
-    field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
-    field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+    field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED";
+    field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED";
+    field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
+    field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS";
     field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
     field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
@@ -17225,10 +17199,6 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public abstract interface NetworkBoundURLFactory {
-    method public abstract java.net.URL getBoundURL(android.net.Network, java.net.URL) throws java.net.MalformedURLException;
-  }
-
   public final class NetworkCapabilities implements android.os.Parcelable {
     ctor public NetworkCapabilities(android.net.NetworkCapabilities);
     method public int describeContents();
@@ -22299,7 +22269,7 @@
     field public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; // 0x20
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
-    field public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1; // 0x1
+    field public static final int WAIT_FOR_DISTANT_PROXIMITY = 1; // 0x1
   }
 
   public final class PowerManager.WakeLock {
@@ -23731,7 +23701,7 @@
     field public static final java.lang.String DATE = "date";
     field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC";
     field public static final java.lang.String DURATION = "duration";
-    field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "extra_call_type_filter";
+    field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.call_type_filter";
     field public static final java.lang.String FEATURES = "features";
     field public static final int FEATURES_NONE = 0; // 0x0
     field public static final int FEATURES_VIDEO = 1; // 0x1
@@ -24402,7 +24372,7 @@
   public static class ContactsContract.Contacts implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
     method public static android.net.Uri getLookupUri(android.content.ContentResolver, android.net.Uri);
     method public static android.net.Uri getLookupUri(long, java.lang.String);
-    method public static boolean isCorpContactId(long);
+    method public static boolean isEnterpriseContactId(long);
     method public static android.net.Uri lookupContact(android.content.ContentResolver, android.net.Uri);
     method public static deprecated void markAsContacted(android.content.ContentResolver, long);
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
@@ -24715,7 +24685,7 @@
     method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
     method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
     field public static final java.lang.String ACTION_QUICK_CONTACT = "com.android.contacts.action.QUICK_CONTACT";
-    field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
+    field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES";
     field public static final int MODE_LARGE = 3; // 0x3
     field public static final int MODE_MEDIUM = 2; // 0x2
     field public static final int MODE_SMALL = 1; // 0x1
@@ -27092,6 +27062,33 @@
 
 }
 
+package android.service.media {
+
+  public abstract class MediaBrowserService extends android.app.Service {
+    ctor public MediaBrowserService();
+    method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public android.media.session.MediaSession.Token getSessionToken();
+    method public void notifyChildrenChanged(android.net.Uri);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
+    method public abstract void onLoadChildren(android.net.Uri, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
+    method public void setSessionToken(android.media.session.MediaSession.Token);
+    field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+  }
+
+  public static final class MediaBrowserService.BrowserRoot {
+    ctor public MediaBrowserService.BrowserRoot(android.net.Uri, android.os.Bundle);
+    method public android.os.Bundle getExtras();
+    method public android.net.Uri getRootUri();
+  }
+
+  public class MediaBrowserService.Result {
+    method public void detach();
+    method public void sendResult(T);
+  }
+
+}
+
 package android.service.notification {
 
   public abstract class NotificationListenerService extends android.app.Service {
@@ -27102,9 +27099,11 @@
     method public final void cancelNotifications(java.lang.String[]);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
+    method public final int getCurrentInterruptionFilter();
     method public final int getCurrentListenerHints();
     method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
     method public android.os.IBinder onBind(android.content.Intent);
+    method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
     method public void onListenerHintsChanged(int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
@@ -27112,13 +27111,12 @@
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
+    method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
-    field public static final int HINTS_NONE = 0; // 0x0
-    field public static final int HINT_HOST_DISABLE_EFFECTS = 4; // 0x4
-    field public static final int HINT_HOST_INTERRUPTION_LEVEL_ALL = 1; // 0x1
-    field public static final int HINT_HOST_INTERRUPTION_LEVEL_NONE = 3; // 0x3
-    field public static final int HINT_HOST_INTERRUPTION_LEVEL_PRIORITY = 2; // 0x2
-    field public static final int HOST_INTERRUPTION_LEVEL_MASK = 3; // 0x3
+    field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
+    field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
+    field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
+    field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
   }
 
@@ -27196,16 +27194,14 @@
 package android.service.voice {
 
   public class AlwaysOnHotwordDetector {
-    method public android.content.Intent getManageIntent(int);
+    method public android.content.Intent createIntentToEnroll();
+    method public android.content.Intent createIntentToReEnroll();
+    method public android.content.Intent createIntentToUnEnroll();
     method public int getSupportedRecognitionModes();
     method public boolean startRecognition(int);
     method public boolean stopRecognition();
-    field public static final int MANAGE_ACTION_ENROLL = 0; // 0x0
-    field public static final int MANAGE_ACTION_RE_ENROLL = 1; // 0x1
-    field public static final int MANAGE_ACTION_UN_ENROLL = 2; // 0x2
     field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
     field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
-    field public static final int RECOGNITION_FLAG_NONE = 0; // 0x0
     field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
     field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
     field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
@@ -27214,7 +27210,8 @@
     field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
   }
 
-  public static abstract interface AlwaysOnHotwordDetector.Callback {
+  public static abstract class AlwaysOnHotwordDetector.Callback {
+    ctor public AlwaysOnHotwordDetector.Callback();
     method public abstract void onAvailabilityChanged(int);
     method public abstract void onDetected(android.service.voice.AlwaysOnHotwordDetector.EventPayload);
     method public abstract void onError();
@@ -32233,17 +32230,23 @@
     field public static final android.util.Rational ZERO;
   }
 
-  public final class Size {
+  public final class Size implements android.os.Parcelable {
     ctor public Size(int, int);
+    method public int describeContents();
     method public int getHeight();
     method public int getWidth();
     method public static android.util.Size parseSize(java.lang.String) throws java.lang.NumberFormatException;
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public final class SizeF {
+  public final class SizeF implements android.os.Parcelable {
     ctor public SizeF(float, float);
+    method public int describeContents();
     method public float getHeight();
     method public float getWidth();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
   public class SparseArray implements java.lang.Cloneable {
@@ -36568,15 +36571,14 @@
   public static abstract class WebChromeClient.FileChooserParams {
     ctor public WebChromeClient.FileChooserParams();
     method public abstract java.lang.String[] getAcceptTypes();
-    method public abstract java.lang.String getDefaultFilename();
+    method public abstract java.lang.String getFilenameHint();
     method public abstract int getMode();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract android.webkit.WebChromeClient.UploadHelper getUploadHelper();
     method public abstract boolean isCaptureEnabled();
-    field public static final int OPEN = 0; // 0x0
-    field public static final int OPEN_FOLDER = 2; // 0x2
-    field public static final int OPEN_MULTIPLE = 1; // 0x1
-    field public static final int SAVE = 3; // 0x3
+    field public static final int MODE_OPEN = 0; // 0x0
+    field public static final int MODE_OPEN_MULTIPLE = 1; // 0x1
+    field public static final int MODE_SAVE = 3; // 0x3
   }
 
   public static abstract class WebChromeClient.UploadHelper {
@@ -39585,22 +39587,6 @@
 
 }
 
-package com.android.internal.telecomm {
-
-  public abstract interface RemoteServiceCallback implements android.os.IInterface {
-    method public abstract void onError() throws android.os.RemoteException;
-    method public abstract void onResult(java.util.List<android.content.ComponentName>, java.util.List<android.os.IBinder>) throws android.os.RemoteException;
-  }
-
-  public static abstract class RemoteServiceCallback.Stub extends android.os.Binder implements com.android.internal.telecomm.RemoteServiceCallback {
-    ctor public RemoteServiceCallback.Stub();
-    method public android.os.IBinder asBinder();
-    method public static com.android.internal.telecomm.RemoteServiceCallback asInterface(android.os.IBinder);
-    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
-  }
-
-}
-
 package com.android.internal.util {
 
   public abstract interface Predicate {
diff --git a/api/removed.txt b/api/removed.txt
index 1b8aef4..8915fc3 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,3 +1,19 @@
+package android {
+
+  public static final class R.attr {
+    field public static final int __removed1 = 16843955; // 0x10104b3
+  }
+
+}
+
+package android.app {
+
+  public class KeyguardManager {
+    method public android.content.Intent getConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
+  }
+
+}
+
 package android.media {
 
   public class AudioFormat {
@@ -32,3 +48,11 @@
 
 }
 
+package com.android.internal {
+
+  public static final class R.attr {
+    field public static final int __removed1 = 16843955; // 0x10104b3
+  }
+
+}
+
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 74ccbc2..6e77e132 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -161,17 +161,17 @@
     LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
             "Error constructing dalvik cache : %s", strerror(errno));
 
-    int result = mkdir(dalvikCacheDir, 0771);
+    int result = mkdir(dalvikCacheDir, 0711);
     LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST),
             "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno));
 
     // We always perform these steps because the directory might
     // already exist, with wider permissions and a different owner
     // than we'd like.
-    result = chown(dalvikCacheDir, AID_SYSTEM, AID_SYSTEM);
+    result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT);
     LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno));
 
-    result = chmod(dalvikCacheDir, 0771);
+    result = chmod(dalvikCacheDir, 0711);
     LOG_ALWAYS_FATAL_IF((result < 0),
             "Error changing dalvik-cache permissions : %s", strerror(errno));
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index c80eeb9..2503d17 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5459,7 +5459,7 @@
      * this method anytime before a return from {@link #onPause()}. If this call is successful
      * then the activity will remain visible when {@link #onPause()} is called, and can continue to
      * play media in the background, but it must stop playing and release resources prior to or
-     * within the call to {@link #onVisibleBehindCancelled()}. If this call returns false, the 
+     * within the call to {@link #onVisibleBehindCanceled()}. If this call returns false, the 
      * activity will not be visible in the background, and must release any media resources 
      * immediately.
      *
@@ -5475,10 +5475,10 @@
      * @return the resulting visibiity state. If true the activity may remain visible beyond
      *      {@link #onPause()}. If false then the activity may not count on being visible behind
      *      other translucent activities, and must stop any media playback and release resources.
-     *      Returning false may occur in lieu of a call to onVisibleBehindCancelled() so the return
+     *      Returning false may occur in lieu of a call to onVisibleBehindCanceled() so the return
      *      value must be checked.
      *
-     * @see #onVisibleBehindCancelled()
+     * @see #onVisibleBehindCanceled()
      * @see #onBackgroundVisibleBehindChanged(boolean)
      */
     public boolean requestVisibleBehind(boolean visible) {
@@ -5498,7 +5498,7 @@
     /**
      * Called when a translucent activity over this activity is becoming opaque or another
      * activity is being launched. Activities that override this method must call
-     * <code>super.onVisibleBehindCancelled()</code> or a SuperNotCalledException will be thrown.
+     * <code>super.onVisibleBehindCanceled()</code> or a SuperNotCalledException will be thrown.
      *
      * <p>When this method is called the activity has 500 msec to release any resources it may be
      * using while visible in the background.
@@ -5509,7 +5509,7 @@
      * @see #requestVisibleBehind(boolean)
      * @see #onBackgroundVisibleBehindChanged(boolean)
      */
-    public void onVisibleBehindCancelled() {
+    public void onVisibleBehindCanceled() {
         mCalled = true;
     }
 
@@ -5521,7 +5521,7 @@
      * {@link #requestVisibleBehind(boolean)}, false otherwise.
      *
      * @see #requestVisibleBehind(boolean)
-     * @see #onVisibleBehindCancelled()
+     * @see #onVisibleBehindCanceled()
      * @see #onBackgroundVisibleBehindChanged(boolean)
      * @hide
      */
@@ -5544,7 +5544,7 @@
      * @param visible true if a background activity is visible, false otherwise.
      *
      * @see #requestVisibleBehind(boolean)
-     * @see #onVisibleBehindCancelled()
+     * @see #onVisibleBehindCanceled()
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ffb9c95..bc54055 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -52,6 +52,7 @@
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
+import android.util.Size;
 import android.util.Slog;
 
 import java.io.FileDescriptor;
@@ -1026,24 +1027,13 @@
     }
 
     /**
-     * Return the current design width for {@link AppTask} thumbnails, for use
+     * Return the current design dimensions for {@link AppTask} thumbnails, for use
      * with {@link #addAppTask}.
      */
-    public int getAppTaskThumbnailWidth() {
+    public Size getAppTaskThumbnailSize() {
         synchronized (this) {
             ensureAppTaskThumbnailSizeLocked();
-            return mAppTaskThumbnailSize.x;
-        }
-    }
-
-    /**
-     * Return the current design height for {@link AppTask} thumbnails, for use
-     * with {@link #addAppTask}.
-     */
-    public int getAppTaskThumbnailHeight() {
-        synchronized (this) {
-            ensureAppTaskThumbnailSizeLocked();
-            return mAppTaskThumbnailSize.y;
+            return new Size(mAppTaskThumbnailSize.x, mAppTaskThumbnailSize.y);
         }
     }
 
@@ -1072,9 +1062,9 @@
      * set on it.
      * @param description Optional additional description information.
      * @param thumbnail Thumbnail to use for the recents entry.  Should be the size given by
-     * {@link #getAppTaskThumbnailWidth()} and {@link #getAppTaskThumbnailHeight()}.  If the
-     * bitmap is not that exact size, it will be recreated in your process, probably in a way
-     * you don't like, before the recents entry is added.
+     * {@link #getAppTaskThumbnailSize()}.  If the bitmap is not that exact size, it will be
+     * recreated in your process, probably in a way you don't like, before the recents entry
+     * is added.
      *
      * @return Returns the task id of the newly added app task, or -1 if the add failed.  The
      * most likely cause of failure is that there is no more room for more tasks for your app.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d70e5df..38999a8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2485,11 +2485,11 @@
             final Activity activity = r.activity;
             if (activity.mVisibleBehind) {
                 activity.mCalled = false;
-                activity.onVisibleBehindCancelled();
+                activity.onVisibleBehindCanceled();
                 // Tick, tick, tick. The activity has 500 msec to return or it will be destroyed.
                 if (!activity.mCalled) {
                     throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
-                            " did not call through to super.onVisibleBehindCancelled()");
+                            " did not call through to super.onVisibleBehindCanceled()");
                 }
                 activity.mVisibleBehind = false;
             }
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index e4f2b88..a09a2e7 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -217,7 +217,10 @@
     }
 
     protected void viewsReady(ArrayMap<String, View> sharedElements) {
-        setSharedElements(sharedElements);
+        sharedElements.retainAll(mAllSharedElementNames);
+        mListener.remapSharedElements(mAllSharedElementNames, sharedElements);
+        mSharedElementNames.addAll(sharedElements.keySet());
+        mSharedElements.addAll(sharedElements.values());
         if (getViewsTransition() != null) {
             getDecor().captureTransitioningViews(mTransitioningViews);
             mTransitioningViews.removeAll(mSharedElements);
@@ -339,32 +342,16 @@
     protected ArrayMap<String, View> mapSharedElements(ArrayList<String> accepted,
             ArrayList<View> localViews) {
         ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
-        if (!mAllSharedElementNames.isEmpty()) {
-            if (accepted != null) {
-                for (int i = 0; i < accepted.size(); i++) {
-                    sharedElements.put(accepted.get(i), localViews.get(i));
-                }
-            } else {
-                getDecor().findNamedViews(sharedElements);
+        if (accepted != null) {
+            for (int i = 0; i < accepted.size(); i++) {
+                sharedElements.put(accepted.get(i), localViews.get(i));
             }
+        } else {
+            getDecor().findNamedViews(sharedElements);
         }
         return sharedElements;
     }
 
-    private void setSharedElements(ArrayMap<String, View> sharedElements) {
-        sharedElements.retainAll(mAllSharedElementNames);
-        mListener.remapSharedElements(mAllSharedElementNames, sharedElements);
-        sharedElements.retainAll(mAllSharedElementNames);
-        for (int i = 0; i < mAllSharedElementNames.size(); i++) {
-            String name = mAllSharedElementNames.get(i);
-            View sharedElement = sharedElements.get(name);
-            if (sharedElement != null) {
-                mSharedElementNames.add(name);
-                mSharedElements.add(sharedElement);
-            }
-        }
-    }
-
     protected void setResultReceiver(ResultReceiver resultReceiver) {
         mResultReceiver = resultReceiver;
     }
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 1e556d6..f79d32b 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -135,6 +135,9 @@
                             mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
                 }
                 break;
+            case BUTTON_NEGATIVE:
+                cancel();
+                break;
         }
     }
 
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 75ecbd9..5a6898d 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -327,7 +327,7 @@
                 public void run() {
                     if (mAnimations++ < MIN_ANIMATION_FRAMES) {
                         getDecor().postOnAnimation(this);
-                    } else {
+                    } else if (mResultReceiver != null) {
                         mResultReceiver.send(MSG_HIDE_SHARED_ELEMENTS, null);
                         mResultReceiver = null; // all done sending messages.
                     }
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 43b9ea8..f31800d 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -174,6 +174,7 @@
                 });
         setGhostVisibility(View.INVISIBLE);
         scheduleGhostVisibilityChange(View.INVISIBLE);
+        mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
         TransitionManager.beginDelayedTransition(getDecor(), transition);
         scheduleGhostVisibilityChange(View.VISIBLE);
         setGhostVisibility(View.VISIBLE);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 07e9a94..214f50c 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -61,6 +61,8 @@
     ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
     void requestHintsFromListener(in INotificationListener token, int hints);
     int getHintsFromListener(in INotificationListener token);
+    void requestInterruptionFilterFromListener(in INotificationListener token, int interruptionFilter);
+    int getInterruptionFilterFromListener(in INotificationListener token);
 
     ComponentName getEffectsSuppressor();
 
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 50e3a10..e055237 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -56,6 +56,13 @@
     public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION";
 
     /**
+     * @removed
+     */
+    public Intent getConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
+        return createConfirmDeviceCredentialIntent(title, description);
+    }
+
+    /**
      * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
      * for the current user of the device. The caller is expected to launch this activity using
      * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
@@ -63,7 +70,7 @@
      *
      * @return the intent for launching the activity or null if no password is required.
      **/
-    public Intent getConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
+    public Intent createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
         if (!isKeyguardSecure()) return null;
         Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
         intent.putExtra(EXTRA_TITLE, title);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index e1dc8bf..8a26ba5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1868,6 +1868,15 @@
         private Notification mRebuildNotification = null;
 
         /**
+         * Whether the build notification has three lines. This is used to make the top padding for
+         * both the contracted and expanded layout consistent.
+         *
+         * <p>
+         * This field is only valid during the build phase.
+         */
+        private boolean mHasThreeLines;
+
+        /**
          * Constructs a new Builder with the defaults:
          *
 
@@ -2564,19 +2573,23 @@
             return this;
         }
 
-        private Bitmap getProfileBadge() {
+        private Drawable getProfileBadgeDrawable() {
             // Note: This assumes that the current user can read the profile badge of the
             // originating user.
             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            Drawable badge = userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0);
+            return userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0);
+        }
+
+        private Bitmap getProfileBadge() {
+            Drawable badge = getProfileBadgeDrawable();
             if (badge == null) {
                 return null;
             }
-            final int width = badge.getIntrinsicWidth();
-            final int height = badge.getIntrinsicHeight();
-            Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            final int size = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.notification_badge_size);
+            Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
             Canvas canvas = new Canvas(bitmap);
-            badge.setBounds(0, 0, width, height);
+            badge.setBounds(0, 0, size, size);
             badge.draw(canvas);
             return bitmap;
         }
@@ -2602,6 +2615,12 @@
             return false;
         }
 
+        private void shrinkLine3Text(RemoteViews contentView) {
+            float subTextSize = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.notification_subtext_size);
+            contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
+        }
+
         private RemoteViews applyStandardTemplate(int resId) {
             RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
                     mOriginatingUserId, resId);
@@ -2674,10 +2693,7 @@
             if (showLine2) {
 
                 // need to shrink all the type to make sure everything fits
-                final Resources res = mContext.getResources();
-                final float subTextSize = res.getDimensionPixelSize(
-                        R.dimen.notification_subtext_size);
-                contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
+                shrinkLine3Text(contentView);
             }
 
             if (mWhen != 0 && mShowWhen) {
@@ -2696,7 +2712,7 @@
 
             // Adjust padding depending on line count and font size.
             contentView.setViewPadding(R.id.line1, 0, calculateTopPadding(mContext,
-                    hasThreeLines(), mContext.getResources().getConfiguration().fontScale),
+                    mHasThreeLines, mContext.getResources().getConfiguration().fontScale),
                     0, 0);
 
             // We want to add badge to first line of text.
@@ -2721,7 +2737,12 @@
          *         is going to have one or two lines
          */
         private boolean hasThreeLines() {
-            boolean hasLine3 = mContentText != null || mContentInfo != null || mNumber > 0;
+            boolean contentTextInLine2 = mSubText != null && mContentText != null;
+
+            // If we have content text in line 2, badge goes into line 2, or line 3 otherwise
+            boolean badgeInLine3 = getProfileBadgeDrawable() != null && !contentTextInLine2;
+            boolean hasLine3 = mContentText != null || mContentInfo != null || mNumber > 0
+                    || badgeInLine3;
             boolean hasLine2 = (mSubText != null && mContentText != null) ||
                     (mSubText == null && (mProgressMax != 0 || mProgressIndeterminate));
             return hasLine2 && hasLine3;
@@ -3092,6 +3113,7 @@
             if (mRebuildNotification == null) {
                 throw new IllegalStateException("rebuild() only valid when in 'rebuild' mode.");
             }
+            mHasThreeLines = hasThreeLines();
 
             Bundle extras = mRebuildNotification.extras;
 
@@ -3124,6 +3146,7 @@
             }
             extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW);
 
+            mHasThreeLines = false;
             return mRebuildNotification;
         }
 
@@ -3238,6 +3261,7 @@
          */
         public Notification build() {
             mOriginatingUserId = mContext.getUserId();
+            mHasThreeLines = hasThreeLines();
 
             Notification n = buildUnstyled();
 
@@ -3259,6 +3283,7 @@
                 mStyle.addExtras(n.extras);
             }
 
+            mHasThreeLines = false;
             return n;
         }
 
@@ -3388,7 +3413,7 @@
          */
         protected void applyTopPadding(RemoteViews contentView) {
             int topPadding = Builder.calculateTopPadding(mBuilder.mContext,
-                    mBuilder.hasThreeLines(),
+                    mBuilder.mHasThreeLines,
                     mBuilder.mContext.getResources().getConfiguration().fontScale);
             contentView.setViewPadding(R.id.line1, 0, topPadding, 0, 0);
         }
@@ -3661,6 +3686,8 @@
 
             applyTopPadding(contentView);
 
+            mBuilder.shrinkLine3Text(contentView);
+
             mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
 
             return contentView;
@@ -3800,6 +3827,8 @@
 
             applyTopPadding(contentView);
 
+            mBuilder.shrinkLine3Text(contentView);
+
             mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
 
             return contentView;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 5c24540..69b1139 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1885,7 +1885,7 @@
      * security exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param disabled Whether or not screen capture should be disabled.
+     * @param disabled Whether screen capture is disabled or not.
      */
     public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) {
         if (mService != null) {
@@ -1920,6 +1920,42 @@
     }
 
     /**
+     * Called by a device owner to set whether auto time is required. If auto time is
+     * required the user cannot set the date and time, but has to use network date and time.
+     *
+     * <p>Note: if auto time is required the user can still manually set the time zone.
+     *
+     * <p>The calling device admin must be a device owner. If it is not, a security exception will
+     * be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param required Whether auto time is set required or not.
+     */
+    public void setAutoTimeRequired(ComponentName admin, boolean required) {
+        if (mService != null) {
+            try {
+                mService.setAutoTimeRequired(admin, UserHandle.myUserId(), required);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * @return true if auto time is required.
+     */
+    public boolean getAutoTimeRequired() {
+        if (mService != null) {
+            try {
+                return mService.getAutoTimeRequired();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by an application that is administering the device to disable keyguard customizations,
      * such as widgets. After setting this, keyguard features will be disabled according to the
      * provided feature list.
@@ -2420,10 +2456,10 @@
      * @throws IllegalArgumentException if the userId is invalid.
      */
     @SystemApi
-    public String getProfileOwnerNameAsUser(UserHandle user) throws IllegalArgumentException {
+    public String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
         if (mService != null) {
             try {
-                return mService.getProfileOwnerName(user.getIdentifier());
+                return mService.getProfileOwnerName(userId);
             } catch (RemoteException re) {
                 Log.w(TAG, "Failed to get profile owner");
                 throw new IllegalArgumentException(
@@ -2526,6 +2562,7 @@
      * @param agent Which component to enable features for.
      * @param features List of features to enable. Consult specific TrustAgent documentation for
      * the feature list.
+     * @hide
      */
     public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
             List<String> features) {
@@ -2546,6 +2583,7 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param agent Which component to get enabled features for.
      * @return List of enabled features.
+     * @hide
      */
     public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent) {
         if (mService != null) {
@@ -2653,10 +2691,10 @@
      * Called by a profile or device owner to set the permitted accessibility services. When
      * set by a device owner or profile owner the restriction applies to all profiles of the
      * user the device owner or profile owner is an admin for.
-     * 
+     *
      * By default the user can use any accessiblity service. When zero or more packages have
      * been added, accessiblity services that are not in the list and not part of the system
-     * can not be enabled by the user. 
+     * can not be enabled by the user.
      *
      * <p> Calling with a null value for the list disables the restriction so that all services
      * can be used, calling with an empty list only allows the builtin system's services.
@@ -3157,6 +3195,20 @@
     /**
      * Called by device owners to update {@link Settings.Global} settings. Validation that the value
      * of the setting is in the correct form for the setting type should be performed by the caller.
+     * <p>The settings that can be updated with this method are:
+     * <ul>
+     * <li>{@link Settings.Global#ADB_ENABLED}</li>
+     * <li>{@link Settings.Global#AUTO_TIME}</li>
+     * <li>{@link Settings.Global#AUTO_TIME_ZONE}</li>
+     * <li>{@link Settings.Global#BLUETOOTH_ON}</li>
+     * <li>{@link Settings.Global#DATA_ROAMING}</li>
+     * <li>{@link Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}</li>
+     * <li>{@link Settings.Global#MODE_RINGER}</li>
+     * <li>{@link Settings.Global#NETWORK_PREFERENCE}</li>
+     * <li>{@link Settings.Global#USB_MASS_STORAGE_ENABLED}</li>
+     * <li>{@link Settings.Global#WIFI_ON}</li>
+     * <li>{@link Settings.Global#WIFI_SLEEP_POLICY}</li>
+     * </ul>
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
@@ -3176,7 +3228,11 @@
      * Called by profile or device owners to update {@link Settings.Secure} settings. Validation
      * that the value of the setting is in the correct form for the setting type should be performed
      * by the caller.
-     *
+     * <p>The settings that can be updated with this method are:
+     * <ul>
+     * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li>
+     * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li>
+     * </ul>
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
      * @param value The value to update the setting to.
@@ -3271,10 +3327,10 @@
      * @param packageName package to check.
      * @return true if the user shouldn't be able to uninstall the package.
      */
-    public boolean getUninstallBlocked(ComponentName admin, String packageName) {
+    public boolean isUninstallBlocked(ComponentName admin, String packageName) {
         if (mService != null) {
             try {
-                return mService.getUninstallBlocked(admin, packageName);
+                return mService.isUninstallBlocked(admin, packageName);
             } catch (RemoteException re) {
                 Log.w(TAG, "Failed to call block uninstall on device policy service");
             }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 1e17bb6..c984cf9 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -174,7 +174,7 @@
     void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userId);
 
     void setUninstallBlocked(in ComponentName admin, in String packageName, boolean uninstallBlocked);
-    boolean getUninstallBlocked(in ComponentName admin, in String packageName);
+    boolean isUninstallBlocked(in ComponentName admin, in String packageName);
 
     void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
     boolean getCrossProfileCallerIdDisabled(in ComponentName who);
@@ -186,4 +186,7 @@
     boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName);
     boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
     List<String> getCrossProfileWidgetProviders(in ComponentName admin);
+
+    void setAutoTimeRequired(in ComponentName who, int userHandle, boolean required);
+    boolean getAutoTimeRequired();
 }
diff --git a/core/java/android/app/backup/BackupHelper.java b/core/java/android/app/backup/BackupHelper.java
index e3f0d54..7cbbbc3 100644
--- a/core/java/android/app/backup/BackupHelper.java
+++ b/core/java/android/app/backup/BackupHelper.java
@@ -37,10 +37,9 @@
  */
 public interface BackupHelper {
     /**
-     * Based on <code>oldState</code>, determine which of the files from the
-     * application's data directory need to be backed up, write them to
-     * <code>data</code>, and fill in <code>newState</code> with the state as it
-     * exists now.
+     * Based on <code>oldState</code>, determine what application content
+     * needs to be backed up, write it to <code>data</code>, and fill in
+     * <code>newState</code> with the complete state as it exists now.
      * <p>
      * Implementing this method is much like implementing
      * {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b13792b..b2b48e8 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -27,6 +27,7 @@
 import android.database.CrossProcessCursorWrapper;
 import android.database.Cursor;
 import android.database.IContentObserver;
+import android.graphics.Point;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -161,6 +162,17 @@
     public static final String SCHEME_FILE = "file";
 
     /**
+     * An extra {@link Point} describing the optimal size for a requested image
+     * resource, in pixels. If a provider has multiple sizes of the image, it
+     * should return the image closest to this size.
+     *
+     * @see #openTypedAssetFileDescriptor(Uri, String, Bundle)
+     * @see #openTypedAssetFileDescriptor(Uri, String, Bundle,
+     *      CancellationSignal)
+     */
+    public static final String EXTRA_SIZE = "android.content.extra.SIZE";
+
+    /**
      * This is the Android platform's base MIME type for a content: URI
      * containing a Cursor of a single item.  Applications should use this
      * as the base type along with their own sub-type of their content: URIs
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index c928a18..44e24b1 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -623,7 +623,7 @@
             try {
                 final ParcelFileDescriptor clientSocket = mSession.openWrite(name,
                         offsetBytes, lengthBytes);
-                return new FileBridge.FileBridgeOutputStream(clientSocket.getFileDescriptor());
+                return new FileBridge.FileBridgeOutputStream(clientSocket);
             } catch (RuntimeException e) {
                 ExceptionUtils.maybeUnwrapIOException(e);
                 throw e;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5492775..fa2bb4d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1456,6 +1456,15 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports live TV and can display
+     * contents from TV inputs implemented with the
+     * {@link android.media.tv.TvInputService} API.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_LIVE_TV = "android.software.live_tv";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports WiFi (802.11) networking.
      */
     @SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index caabed3..ca0935c 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -26,8 +26,8 @@
      * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
      */
 
-    oneway void onCameraError(int errorCode, in CaptureResultExtras resultExtras);
-    oneway void onCameraIdle();
+    oneway void onDeviceError(int errorCode, in CaptureResultExtras resultExtras);
+    oneway void onDeviceIdle();
     oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
     oneway void onResultReceived(in CameraMetadataNative result,
                                  in CaptureResultExtras resultExtras);
diff --git a/core/java/android/hardware/camera2/TotalCaptureResult.java b/core/java/android/hardware/camera2/TotalCaptureResult.java
index ec4bc7d..0895fe3 100644
--- a/core/java/android/hardware/camera2/TotalCaptureResult.java
+++ b/core/java/android/hardware/camera2/TotalCaptureResult.java
@@ -19,6 +19,7 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.CaptureResultExtras;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -48,13 +49,23 @@
  */
 public final class TotalCaptureResult extends CaptureResult {
 
+    private final List<CaptureResult> mPartialResults;
+
     /**
-     * Takes ownership of the passed-in properties object
+     * Takes ownership of the passed-in camera metadata and the partial results
+     *
+     * @param partials a list of partial results; {@code null} will be substituted for an empty list
      * @hide
      */
     public TotalCaptureResult(CameraMetadataNative results, CaptureRequest parent,
-            CaptureResultExtras extras) {
+            CaptureResultExtras extras, List<CaptureResult> partials) {
         super(results, parent, extras);
+
+        if (partials == null) {
+            mPartialResults = new ArrayList<>();
+        } else {
+            mPartialResults = partials;
+        }
     }
 
     /**
@@ -65,6 +76,8 @@
      */
     public TotalCaptureResult(CameraMetadataNative results, int sequenceId) {
         super(results, sequenceId);
+
+        mPartialResults = new ArrayList<>();
     }
 
     /**
@@ -73,14 +86,13 @@
      * <p>The list is returned is unmodifiable; attempting to modify it will result in a
      * {@code UnsupportedOperationException} being thrown.</p>
      *
-     * <p>The list size will be inclusive between {@code 1} and
-     * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}, in ascending order
+     * <p>The list size will be inclusive between {@code 0} and
+     * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}, with elements in ascending order
      * of when {@link CameraCaptureSession.CaptureListener#onCaptureProgressed} was invoked.</p>
      *
      * @return unmodifiable list of partial results
      */
     public List<CaptureResult> getPartialResults() {
-        // TODO
-        return Collections.unmodifiableList(null);
+        return Collections.unmodifiableList(mPartialResults);
     }
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 621968b..9ca1fba 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -74,7 +74,7 @@
     private boolean mSkipUnconfigure = false;
 
     /** Is the session in the process of aborting? Pay attention to BUSY->IDLE transitions. */
-    private boolean mAborting;
+    private volatile boolean mAborting;
 
     /**
      * Create a new CameraCaptureSession.
@@ -346,6 +346,20 @@
     }
 
     /**
+     * Whether currently in mid-abort.
+     *
+     * <p>This is used by the implementation to set the capture failure
+     * reason, in lieu of more accurate error codes from the camera service.
+     * Unsynchronized to avoid deadlocks between simultaneous session->device,
+     * device->session calls.</p>
+     *
+     * <p>Package-private.</p>
+     */
+    boolean isAborting() {
+        return mAborting;
+    }
+
+    /**
      * Post calls into a CameraCaptureSession.StateListener to the user-specified {@code handler}.
      */
     private StateListener createUserStateListenerProxy(Handler handler, StateListener listener) {
@@ -502,8 +516,8 @@
 
                 // TODO: Queue captures during abort instead of failing them
                 // since the app won't be able to distinguish the two actives
+                // Don't signal the application since there's no clean mapping here
                 Log.w(TAG, "Device is now busy; do not submit new captures (TODO: allow this)");
-                mStateListener.onActive(session);
             }
 
             @Override
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 79ce9df..f5666bf 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -41,6 +41,7 @@
 
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -384,7 +385,7 @@
                 catch (IllegalArgumentException e) {
                     // OK. camera service can reject stream config if it's not supported by HAL
                     // This is only the result of a programmer misusing the camera2 api.
-                    Log.e(TAG, "Stream configuration failed", e);
+                    Log.w(TAG, "Stream configuration failed");
                     return false;
                 }
 
@@ -721,6 +722,13 @@
             checkIfCameraClosedOrInError();
 
             mDeviceHandler.post(mCallOnBusy);
+
+            // If already idle, just do a busy->idle transition immediately, don't actually
+            // flush.
+            if (mIdle) {
+                mDeviceHandler.post(mCallOnIdle);
+                return;
+            }
             try {
                 LongParcelable lastFrameNumberRef = new LongParcelable();
                 mRemoteDevice.flush(/*out*/lastFrameNumberRef);
@@ -960,6 +968,8 @@
 
         private long mCompletedFrameNumber = -1;
         private final TreeSet<Long> mFutureErrorSet = new TreeSet<Long>();
+        /** Map frame numbers to list of partial results */
+        private final HashMap<Long, List<CaptureResult>> mPartialResults = new HashMap<>();
 
         private void update() {
             Iterator<Long> iter = mFutureErrorSet.iterator();
@@ -976,8 +986,8 @@
 
         /**
          * This function is called every time when a result or an error is received.
-         * @param frameNumber: the frame number corresponding to the result or error
-         * @param isError: true if it is an error, false if it is not an error
+         * @param frameNumber the frame number corresponding to the result or error
+         * @param isError true if it is an error, false if it is not an error
          */
         public void updateTracker(long frameNumber, boolean isError) {
             if (isError) {
@@ -999,6 +1009,55 @@
             update();
         }
 
+        /**
+         * This function is called every time a result has been completed.
+         *
+         * <p>It keeps a track of all the partial results already created for a particular
+         * frame number.</p>
+         *
+         * @param frameNumber the frame number corresponding to the result
+         * @param result the total or partial result
+         * @param partial {@true} if the result is partial, {@code false} if total
+         */
+        public void updateTracker(long frameNumber, CaptureResult result, boolean partial) {
+
+            if (!partial) {
+                // Update the total result's frame status as being successful
+                updateTracker(frameNumber, /*isError*/false);
+                // Don't keep a list of total results, we don't need to track them
+                return;
+            }
+
+            if (result == null) {
+                // Do not record blank results; this also means there will be no total result
+                // so it doesn't matter that the partials were not recorded
+                return;
+            }
+
+            // Partial results must be aggregated in-order for that frame number
+            List<CaptureResult> partials = mPartialResults.get(frameNumber);
+            if (partials == null) {
+                partials = new ArrayList<>();
+                mPartialResults.put(frameNumber, partials);
+            }
+
+            partials.add(result);
+        }
+
+        /**
+         * Attempt to pop off all of the partial results seen so far for the {@code frameNumber}.
+         *
+         * <p>Once popped-off, the partial results are forgotten (unless {@code updateTracker}
+         * is called again with new partials for that frame number).</p>
+         *
+         * @param frameNumber the frame number corresponding to the result
+         * @return a list of partial results for that frame with at least 1 element,
+         *         or {@code null} if there were no partials recorded for that frame
+         */
+        public List<CaptureResult> popPartialResults(long frameNumber) {
+            return mPartialResults.remove(frameNumber);
+        }
+
         public long getCompletedFrameNumber() {
             return mCompletedFrameNumber;
         }
@@ -1097,31 +1156,51 @@
          */
         static final int ERROR_CAMERA_SERVICE = 2;
 
+        /**
+         * Camera has encountered an error processing a single request.
+         */
+        static final int ERROR_CAMERA_REQUEST = 3;
+
+        /**
+         * Camera has encountered an error producing metadata for a single capture
+         */
+        static final int ERROR_CAMERA_RESULT = 4;
+
+        /**
+         * Camera has encountered an error producing an image buffer for a single capture
+         */
+        static final int ERROR_CAMERA_BUFFER = 5;
+
         @Override
         public IBinder asBinder() {
             return this;
         }
 
         @Override
-        public void onCameraError(final int errorCode, CaptureResultExtras resultExtras) {
-            Runnable r = null;
+        public void onDeviceError(final int errorCode, CaptureResultExtras resultExtras) {
+            if (DEBUG) {
+                Log.d(TAG, String.format(
+                    "Device error received, code %d, frame number %d, request ID %d, subseq ID %d",
+                    errorCode, resultExtras.getFrameNumber(), resultExtras.getRequestId(),
+                    resultExtras.getSubsequenceId()));
+            }
 
             synchronized(mInterfaceLock) {
                 if (mRemoteDevice == null) {
                     return; // Camera already closed
                 }
 
-                mInError = true;
                 switch (errorCode) {
                     case ERROR_CAMERA_DISCONNECTED:
-                        r = mCallOnDisconnected;
+                        CameraDeviceImpl.this.mDeviceHandler.post(mCallOnDisconnected);
                         break;
                     default:
                         Log.e(TAG, "Unknown error from camera device: " + errorCode);
                         // no break
                     case ERROR_CAMERA_DEVICE:
                     case ERROR_CAMERA_SERVICE:
-                        r = new Runnable() {
+                        mInError = true;
+                        Runnable r = new Runnable() {
                             @Override
                             public void run() {
                                 if (!CameraDeviceImpl.this.isClosed()) {
@@ -1129,21 +1208,19 @@
                                 }
                             }
                         };
+                        CameraDeviceImpl.this.mDeviceHandler.post(r);
+                        break;
+                    case ERROR_CAMERA_REQUEST:
+                    case ERROR_CAMERA_RESULT:
+                    case ERROR_CAMERA_BUFFER:
+                        onCaptureErrorLocked(errorCode, resultExtras);
                         break;
                 }
-                CameraDeviceImpl.this.mDeviceHandler.post(r);
-
-                // Fire onCaptureSequenceCompleted
-                if (DEBUG) {
-                    Log.v(TAG, String.format("got error frame %d", resultExtras.getFrameNumber()));
-                }
-                mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true);
-                checkAndFireSequenceComplete();
             }
         }
 
         @Override
-        public void onCameraIdle() {
+        public void onDeviceIdle() {
             if (DEBUG) {
                 Log.d(TAG, "Camera now idle");
             }
@@ -1219,12 +1296,6 @@
                 boolean isPartialResult =
                         (resultExtras.getPartialResultCount() < mTotalPartialCount);
 
-                // Update tracker (increment counter) when it's not a partial result.
-                if (!isPartialResult) {
-                    mFrameNumberTracker.updateTracker(frameNumber,
-                            /*error*/false);
-                }
-
                 // Check if we have a listener for this
                 if (holder == null) {
                     if (DEBUG) {
@@ -1232,6 +1303,9 @@
                                 "holder is null, early return at frame "
                                         + frameNumber);
                     }
+
+                    mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult);
+
                     return;
                 }
 
@@ -1241,14 +1315,17 @@
                                 "camera is closed, early return at frame "
                                         + frameNumber);
                     }
+
+                    mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult);
                     return;
                 }
 
                 final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId());
 
-
                 Runnable resultDispatch = null;
 
+                CaptureResult finalResult;
+
                 // Either send a partial result or the final capture completed result
                 if (isPartialResult) {
                     final CaptureResult resultAsCapture =
@@ -1266,9 +1343,14 @@
                             }
                         }
                     };
+
+                    finalResult = resultAsCapture;
                 } else {
+                    List<CaptureResult> partialResults =
+                            mFrameNumberTracker.popPartialResults(frameNumber);
+
                     final TotalCaptureResult resultAsCapture =
-                            new TotalCaptureResult(result, request, resultExtras);
+                            new TotalCaptureResult(result, request, resultExtras, partialResults);
 
                     // Final capture result
                     resultDispatch = new Runnable() {
@@ -1282,19 +1364,80 @@
                             }
                         }
                     };
+
+                    finalResult = resultAsCapture;
                 }
 
                 holder.getHandler().post(resultDispatch);
 
+                // Collect the partials for a total result; or mark the frame as totally completed
+                mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult);
+
                 // Fire onCaptureSequenceCompleted
                 if (!isPartialResult) {
                     checkAndFireSequenceComplete();
                 }
-
             }
         }
 
-    }
+        /**
+         * Called by onDeviceError for handling single-capture failures.
+         */
+        private void onCaptureErrorLocked(int errorCode, CaptureResultExtras resultExtras) {
+
+            final int requestId = resultExtras.getRequestId();
+            final int subsequenceId = resultExtras.getSubsequenceId();
+            final long frameNumber = resultExtras.getFrameNumber();
+            final CaptureListenerHolder holder =
+                    CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+
+            final CaptureRequest request = holder.getRequest(subsequenceId);
+
+            // No way to report buffer errors right now
+            if (errorCode == ERROR_CAMERA_BUFFER) {
+                Log.e(TAG, String.format("Lost output buffer reported for frame %d", frameNumber));
+                return;
+            }
+
+            boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
+
+            // This is only approximate - exact handling needs the camera service and HAL to
+            // disambiguate between request failures to due abort and due to real errors.
+            // For now, assume that if the session believes we're mid-abort, then the error
+            // is due to abort.
+            int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
+                    CaptureFailure.REASON_FLUSHED :
+                    CaptureFailure.REASON_ERROR;
+
+            final CaptureFailure failure = new CaptureFailure(
+                request,
+                reason,
+                /*dropped*/ mayHaveBuffers,
+                requestId,
+                frameNumber);
+
+            Runnable failureDispatch = new Runnable() {
+                @Override
+                public void run() {
+                    if (!CameraDeviceImpl.this.isClosed()){
+                        holder.getListener().onCaptureFailed(
+                            CameraDeviceImpl.this,
+                            request,
+                            failure);
+                    }
+                }
+            };
+            holder.getHandler().post(failureDispatch);
+
+            // Fire onCaptureSequenceCompleted if appropriate
+            if (DEBUG) {
+                Log.v(TAG, String.format("got error frame %d", frameNumber));
+            }
+            mFrameNumberTracker.updateTracker(frameNumber, /*error*/true);
+            checkAndFireSequenceComplete();
+        }
+
+    } // public class CameraDeviceCallbacks
 
     /**
      * Default handler management.
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 5cbf109..410934e 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -211,7 +211,7 @@
         }
 
         @Override
-        public void onCameraError(final int errorCode, final CaptureResultExtras resultExtras) {
+        public void onDeviceError(final int errorCode, final CaptureResultExtras resultExtras) {
             Message msg = getHandler().obtainMessage(CAMERA_ERROR,
                 /*arg1*/ errorCode, /*arg2*/ 0,
                 /*obj*/ resultExtras);
@@ -219,7 +219,7 @@
         }
 
         @Override
-        public void onCameraIdle() {
+        public void onDeviceIdle() {
             Message msg = getHandler().obtainMessage(CAMERA_IDLE);
             getHandler().sendMessage(msg);
         }
@@ -267,11 +267,11 @@
                         case CAMERA_ERROR: {
                             int errorCode = msg.arg1;
                             CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
-                            mCallbacks.onCameraError(errorCode, resultExtras);
+                            mCallbacks.onDeviceError(errorCode, resultExtras);
                             break;
                         }
                         case CAMERA_IDLE:
-                            mCallbacks.onCameraIdle();
+                            mCallbacks.onDeviceIdle();
                             break;
                         case CAPTURE_STARTED: {
                             long timestamp = msg.arg2 & 0xFFFFFFFFL;
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 1cf7797..ffc55f1 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -97,7 +97,7 @@
                         Log.d(TAG, "doing onError callback.");
                     }
                     try {
-                        mDeviceCallbacks.onCameraError(errorCode, extras);
+                        mDeviceCallbacks.onDeviceError(errorCode, extras);
                     } catch (RemoteException e) {
                         throw new IllegalStateException(
                                 "Received remote exception during onCameraError callback: ", e);
@@ -125,7 +125,7 @@
                         Log.d(TAG, "doing onIdle callback.");
                     }
                     try {
-                        mDeviceCallbacks.onCameraIdle();
+                        mDeviceCallbacks.onDeviceIdle();
                     } catch (RemoteException e) {
                         throw new IllegalStateException(
                                 "Received remote exception during onCameraIdle callback: ", e);
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
index 85e7531b..2ec6126 100644
--- a/core/java/android/hardware/hdmi/HdmiPortInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -166,7 +166,7 @@
     public String toString() {
         StringBuffer s = new StringBuffer();
         s.append("port_id: ").append(mId).append(", ");
-        s.append("address: ").append(mAddress).append(", ");
+        s.append("address: ").append(String.format("0x%04x", mAddress)).append(", ");
         s.append("cec: ").append(mCecSupported).append(", ");
         s.append("arc: ").append(mArcSupported).append(", ");
         s.append("mhl: ").append(mMhlSupported);
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 22da90e..8df9916 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -45,7 +45,7 @@
     private volatile AsyncChannel mAsyncChannel;
     private final String LOG_TAG;
     private static final boolean DBG = true;
-    private static final boolean VDBG = true;
+    private static final boolean VDBG = false;
     private final Context mContext;
     private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
 
@@ -134,7 +134,7 @@
             throw new IllegalArgumentException();
         }
 
-        if (DBG) log("Registering NetworkAgent");
+        if (VDBG) log("Registering NetworkAgent");
         ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
                 Context.CONNECTIVITY_SERVICE);
         cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
@@ -148,7 +148,7 @@
                 if (mAsyncChannel != null) {
                     log("Received new connection while already connected!");
                 } else {
-                    if (DBG) log("NetworkAgent fully connected");
+                    if (VDBG) log("NetworkAgent fully connected");
                     AsyncChannel ac = new AsyncChannel();
                     ac.connected(null, this, msg.replyTo);
                     ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
@@ -164,7 +164,7 @@
                 break;
             }
             case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
-                if (DBG) log("CMD_CHANNEL_DISCONNECT");
+                if (VDBG) log("CMD_CHANNEL_DISCONNECT");
                 if (mAsyncChannel != null) mAsyncChannel.disconnect();
                 break;
             }
diff --git a/core/java/android/net/NetworkBoundURLFactory.java b/core/java/android/net/NetworkBoundURLFactory.java
deleted file mode 100644
index 356100e..0000000
--- a/core/java/android/net/NetworkBoundURLFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * An interface that describes a factory for network-specific {@link URL} objects.
- */
-public interface NetworkBoundURLFactory {
-    /**
-     * Returns a {@link URL} based on the given URL but bound to the specified {@code Network},
-     * such that opening the URL will send all network traffic on the specified Network.
-     *
-     * @return a {@link URL} bound to this {@code Network}.
-     * @throws MalformedURLException if the URL was not valid, or this factory cannot handle the
-     *         specified URL (e.g., if it does not support the protocol of the URL).
-     */
-    public URL getBoundURL(Network network, URL url) throws MalformedURLException;
-}
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index a20e8e7..6ddd8b3 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -46,6 +46,7 @@
  **/
 public class NetworkFactory extends Handler {
     private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
     /**
@@ -164,13 +165,14 @@
     private void handleAddRequest(NetworkRequest request, int score) {
         NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
         if (n == null) {
+            if (DBG) log("got request " + request + " with score " + score);
             n = new NetworkRequestInfo(request, score);
             mNetworkRequests.put(n.request.requestId, n);
         } else {
+            if (VDBG) log("new score " + score + " for exisiting request " + request);
             n.score = score;
         }
-        if (DBG) log("got request " + request + " with score " + score);
-        if (DBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);
+        if (VDBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);
 
         evalRequest(n);
     }
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index bf8d15c..022a106 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -131,10 +131,17 @@
     }
 
     public static class FileBridgeOutputStream extends OutputStream {
+        private final ParcelFileDescriptor mClientPfd;
         private final FileDescriptor mClient;
         private final byte[] mTemp = new byte[MSG_LENGTH];
 
+        public FileBridgeOutputStream(ParcelFileDescriptor clientPfd) {
+            mClientPfd = clientPfd;
+            mClient = clientPfd.getFileDescriptor();
+        }
+
         public FileBridgeOutputStream(FileDescriptor client) {
+            mClientPfd = null;
             mClient = client;
         }
 
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index f7b0ead..00e2e22 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -248,7 +248,7 @@
      * {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor
      * indicates that an object is not in close proximity.
      */
-    public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
+    public static final int WAIT_FOR_DISTANT_PROXIMITY = 1;
 
     /**
      * Brightness value for fully on.
@@ -961,7 +961,8 @@
          * </p>
          *
          * @param flags Combination of flag values to modify the release behavior.
-         * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
+         * Currently only {@link #WAIT_FOR_DISTANT_PROXIMITY} is supported. Passing 0 is
+         * equivalent to calling {@link #release()}.
          */
         public void release(int flags) {
             synchronized (mToken) {
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 942da5a..0202f91 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -116,7 +116,8 @@
          * </pre>
          * </p>
          */
-        public static final String EXTRA_CALL_TYPE_FILTER = "extra_call_type_filter";
+        public static final String EXTRA_CALL_TYPE_FILTER
+                = "android.provider.extra.call_type_filter";
 
         /**
          * Content uri used to access call log entries, including voicemail records. You must have
@@ -349,6 +350,15 @@
         public static final String PHONE_ACCOUNT_ID = "subscription_id";
 
         /**
+         * The identifier of a account that is unique to a specified component. Equivalent value
+         * to {@link #PHONE_ACCOUNT_ID}. For ContactsProvider internal use only.
+         * <P>Type: INTEGER</P>
+         *
+         * @hide
+         */
+        public static final String SUB_ID = "sub_id";
+
+        /**
          * If a successful call is made that is longer than this duration, update the phone number
          * in the ContactsProvider with the normalized version of the number, based on the user's
          * current country code.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 513e47e..27473e3 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -36,7 +36,6 @@
 import android.database.DatabaseUtils;
 import android.graphics.Rect;
 import android.net.Uri;
-import android.net.Uri.Builder;
 import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
@@ -1622,15 +1621,15 @@
          *
          * @hide
          */
-        public static long CORP_CONTACT_ID_BASE = 1000000000; // slightly smaller than 2 ** 30
+        public static long ENTERPRISE_CONTACT_ID_BASE = 1000000000; // slightly smaller than 2 ** 30
 
         /**
-         * Return TRUE if a contact ID is from the contacts provider on the corp profile.
+         * Return TRUE if a contact ID is from the contacts provider on the enterprise profile.
          *
          * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI} may return such a contact.
          */
-        public static boolean isCorpContactId(long contactId) {
-            return (contactId >= CORP_CONTACT_ID_BASE) && (contactId < Profile.MIN_ID);
+        public static boolean isEnterpriseContactId(long contactId) {
+            return (contactId >= ENTERPRISE_CONTACT_ID_BASE) && (contactId < Profile.MIN_ID);
         }
 
         /**
@@ -2229,6 +2228,11 @@
          * type.  For applications that need to be aware of the data set, this can
          * be used instead of account type to distinguish sets of data.  This is
          * never intended to be used for specifying accounts.
+         * <p>
+         * This column does *not* escape forward slashes in the account type or the data set.
+         * If this is an issue, consider using
+         * {@link ContactsContract.RawContacts#ACCOUNT_TYPE} and
+         * {@link ContactsContract.RawContacts#DATA_SET} directly.
          */
         public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
 
@@ -5025,7 +5029,8 @@
          *     </li>
          *     <li>
          *     Corp contacts will get artificial {@link #_ID}s.  In order to tell whether a contact
-         *     is from the corp profile, use {@link ContactsContract.Contacts#isCorpContactId(long)}.
+         *     is from the corp profile, use
+         *     {@link ContactsContract.Contacts#isEnterpriseContactId(long)}.
          *     </li>
          * </ul>
          * <p>
@@ -8114,19 +8119,19 @@
          * @hide
          */
         @Deprecated
-        public static final String EXTRA_TARGET_RECT = "target_rect";
+        public static final String EXTRA_TARGET_RECT = "android.provider.extra.TARGET_RECT";
 
         /**
          * Extra used to specify size of pivot dialog.
          * @hide
          */
-        public static final String EXTRA_MODE = "mode";
+        public static final String EXTRA_MODE = "android.provider.extra.MODE";
 
         /**
          * Extra used to indicate a list of specific MIME-types to exclude and not display in the
          * QuickContacts dialog. Stored as a {@link String} array.
          */
-        public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
+        public static final String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES";
 
         /**
          * Small QuickContact mode, usually presented with minimal actions.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 327fe4a..9a0858a 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -511,8 +511,6 @@
     public static final String METHOD_DELETE_DOCUMENT = "android:deleteDocument";
 
     /** {@hide} */
-    public static final String EXTRA_THUMBNAIL_SIZE = "thumbnail_size";
-    /** {@hide} */
     public static final String EXTRA_URI = "uri";
 
     private static final String PATH_ROOT = "root";
@@ -819,7 +817,7 @@
             ContentProviderClient client, Uri documentUri, Point size, CancellationSignal signal)
             throws RemoteException, IOException {
         final Bundle openOpts = new Bundle();
-        openOpts.putParcelable(DocumentsContract.EXTRA_THUMBNAIL_SIZE, size);
+        openOpts.putParcelable(ContentResolver.EXTRA_SIZE, size);
 
         AssetFileDescriptor afd = null;
         Bitmap bitmap = null;
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 021fff4..270d786 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -16,7 +16,6 @@
 
 package android.provider;
 
-import static android.provider.DocumentsContract.EXTRA_THUMBNAIL_SIZE;
 import static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_RENAME_DOCUMENT;
@@ -763,8 +762,8 @@
     public final AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
             throws FileNotFoundException {
         enforceTree(uri);
-        if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
-            final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
+        if (opts != null && opts.containsKey(ContentResolver.EXTRA_SIZE)) {
+            final Point sizeHint = opts.getParcelable(ContentResolver.EXTRA_SIZE);
             return openDocumentThumbnail(getDocumentId(uri), sizeHint, null);
         } else {
             return super.openTypedAssetFile(uri, mimeTypeFilter, opts);
@@ -781,8 +780,8 @@
             Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
             throws FileNotFoundException {
         enforceTree(uri);
-        if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
-            final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
+        if (opts != null && opts.containsKey(ContentResolver.EXTRA_SIZE)) {
+            final Point sizeHint = opts.getParcelable(ContentResolver.EXTRA_SIZE);
             return openDocumentThumbnail(getDocumentId(uri), sizeHint, signal);
         } else {
             return super.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 95d1351..ae11f47 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2113,6 +2113,13 @@
         public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
 
         /**
+         * Microphone mute (int 1 = mute, 0 = not muted).
+         *
+         * @hide
+         */
+        public static final String MICROPHONE_MUTE = "microphone_mute";
+
+        /**
          * Whether the notifications should use the ring volume (value of 1) or
          * a separate notification volume (value of 0). In most cases, users
          * will have this enabled so the notification and ringer volumes will be
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 93b2d3b..8ca9b6c 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -29,4 +29,5 @@
             in NotificationRankingUpdate update);
     void onNotificationRankingUpdate(in NotificationRankingUpdate update);
     void onListenerHintsChanged(int hints);
-}
\ No newline at end of file
+    void onInterruptionFilterChanged(int interruptionFilter);
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 450b9a7..a544b2d 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -58,26 +58,28 @@
     private final String TAG = NotificationListenerService.class.getSimpleName()
             + "[" + getClass().getSimpleName() + "]";
 
-    /** {@link #getCurrentListenerHints() Listener hints} constant - default state. */
-    public static final int HINTS_NONE = 0;
+    /**
+     * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+     *     Normal interruption filter.
+     */
+    public static final int INTERRUPTION_FILTER_ALL = 1;
 
-    /** Bitmask range for {@link #getCurrentListenerHints() Listener hints} host interruption level
-     * constants.  */
-    public static final int HOST_INTERRUPTION_LEVEL_MASK = 0x3;
+    /**
+     * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+     *     Priority interruption filter.
+     */
+    public static final int INTERRUPTION_FILTER_PRIORITY = 2;
 
-    /** {@link #getCurrentListenerHints() Listener hints} constant - Normal interruption level. */
-    public static final int HINT_HOST_INTERRUPTION_LEVEL_ALL = 1;
-
-    /** {@link #getCurrentListenerHints() Listener hints} constant - Priority interruption level. */
-    public static final int HINT_HOST_INTERRUPTION_LEVEL_PRIORITY = 2;
-
-    /** {@link #getCurrentListenerHints() Listener hints} constant - No interruptions level. */
-    public static final int HINT_HOST_INTERRUPTION_LEVEL_NONE = 3;
+    /**
+     * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+     *     No interruptions filter.
+     */
+    public static final int INTERRUPTION_FILTER_NONE = 3;
 
     /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
      * should disable notification sound, vibrating and other visual or aural effects.
-     * This does not change the interruption level, only the effects. **/
-    public static final int HINT_HOST_DISABLE_EFFECTS = 1 << 2;
+     * This does not change the interruption filter, only the effects. **/
+    public static final int HINT_HOST_DISABLE_EFFECTS = 1;
 
     private INotificationListenerWrapper mWrapper = null;
     private RankingMap mRankingMap;
@@ -197,6 +199,17 @@
         // optional
     }
 
+    /**
+     * Implement this method to be notified when the
+     * {@link #getCurrentInterruptionFilter() interruption filter} changed.
+     *
+     * @param interruptionFilter The current
+     *     {@link #getCurrentInterruptionFilter() interruption filter}.
+     */
+    public void onInterruptionFilterChanged(int interruptionFilter) {
+        // optional
+    }
+
     private final INotificationManager getNotificationInterface() {
         if (mNoMan == null) {
             mNoMan = INotificationManager.Stub.asInterface(
@@ -345,15 +358,42 @@
      * shared across all listeners or a feature the notification host does not support or refuses
      * to grant.
      *
-     * @return One or more of the HINT_ constants.
+     * @return Zero or more of the HINT_ constants.
      */
     public final int getCurrentListenerHints() {
-        if (!isBound()) return HINTS_NONE;
+        if (!isBound()) return 0;
         try {
             return getNotificationInterface().getHintsFromListener(mWrapper);
         } catch (android.os.RemoteException ex) {
             Log.v(TAG, "Unable to contact notification manager", ex);
-            return HINTS_NONE;
+            return 0;
+        }
+    }
+
+    /**
+     * Gets the current notification interruption filter active on the host.
+     *
+     * <p>
+     * The interruption filter defines which notifications are allowed to interrupt the user
+     * (e.g. via sound &amp; vibration) and is applied globally. Listeners can find out whether
+     * a specific notification matched the interruption filter via
+     * {@link Ranking#matchesInterruptionFilter()}.
+     * <p>
+     * The current filter may differ from the previously requested filter if the notification host
+     * does not support or refuses to apply the requested filter, or if another component changed
+     * the filter in the meantime.
+     * <p>
+     * Listen for updates using {@link #onInterruptionFilterChanged(int)}.
+     *
+     * @return One of the INTERRUPTION_FILTER_ constants, or 0 on errors.
+     */
+    public final int getCurrentInterruptionFilter() {
+        if (!isBound()) return 0;
+        try {
+            return getNotificationInterface().getHintsFromListener(mWrapper);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+            return 0;
         }
     }
 
@@ -361,7 +401,7 @@
      * Sets the desired {@link #getCurrentListenerHints() listener hints}.
      *
      * <p>
-     * This is merely a request, the host may or not choose to take action depending
+     * This is merely a request, the host may or may not choose to take action depending
      * on other listener requests or other global state.
      * <p>
      * Listen for updates using {@link #onListenerHintsChanged(int)}.
@@ -378,6 +418,27 @@
     }
 
     /**
+     * Sets the desired {@link #getCurrentInterruptionFilter() interruption filter}.
+     *
+     * <p>
+     * This is merely a request, the host may or may not choose to apply the requested
+     * interruption filter depending on other listener requests or other global state.
+     * <p>
+     * Listen for updates using {@link #onInterruptionFilterChanged(int)}.
+     *
+     * @param interruptionFilter One of the INTERRUPTION_FILTER_ constants.
+     */
+    public final void requestInterruptionFilter(int interruptionFilter) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface()
+                    .requestInterruptionFilterFromListener(mWrapper, interruptionFilter);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
      * Returns current ranking information.
      *
      * <p>
@@ -514,6 +575,15 @@
                 Log.w(TAG, "Error running onListenerHintsChanged", t);
             }
         }
+
+        @Override
+        public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException {
+            try {
+                NotificationListenerService.this.onInterruptionFilterChanged(interruptionFilter);
+            } catch (Throwable t) {
+                Log.w(TAG, "Error running onInterruptionFilterChanged", t);
+            }
+        }
     }
 
     private void applyUpdate(NotificationRankingUpdate update) {
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 337ae60..3ef5b37 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -89,6 +89,7 @@
     /**
      * A white list of features that the given trust agent should support when otherwise disabled
      * by device policy.
+     * @hide
      */
     public static final String KEY_FEATURES = "trust_agent_features";
 
@@ -184,6 +185,7 @@
      *
      * @param options Option feature bundle.
      * @return true if the {@link TrustAgentService} supports this feature.
+     * @hide
      */
     public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
         return false;
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 2095773..519bc28 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.Activity;
 import android.content.Intent;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
@@ -84,20 +85,31 @@
     private static final int STATE_NOT_READY = 0;
 
     // Keyphrase management actions. Used in getManageIntent() ----//
-    /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
                 MANAGE_ACTION_ENROLL,
                 MANAGE_ACTION_RE_ENROLL,
                 MANAGE_ACTION_UN_ENROLL
             })
-    public @interface ManageActions {}
+    private @interface ManageActions {}
 
-    /** Indicates that we need to enroll. */
+    /**
+     * Indicates that we need to enroll.
+     *
+     * @hide
+     */
     public static final int MANAGE_ACTION_ENROLL = 0;
-    /** Indicates that we need to re-enroll. */
+    /**
+     * Indicates that we need to re-enroll.
+     *
+     * @hide
+     */
     public static final int MANAGE_ACTION_RE_ENROLL = 1;
-    /** Indicates that we need to un-enroll. */
+    /**
+     * Indicates that we need to un-enroll.
+     *
+     * @hide
+     */
     public static final int MANAGE_ACTION_UN_ENROLL = 2;
 
     //-- Flags for startRecognition    ----//
@@ -111,7 +123,11 @@
             })
     public @interface RecognitionFlags {}
 
-    /** Empty flag for {@link #startRecognition(int)}. */
+    /**
+     * Empty flag for {@link #startRecognition(int)}.
+     *
+     * @hide
+     */
     public static final int RECOGNITION_FLAG_NONE = 0;
     /**
      * Recognition flag for {@link #startRecognition(int)} that indicates
@@ -264,7 +280,7 @@
     /**
      * Callbacks for always-on hotword detection.
      */
-    public interface Callback {
+    public static abstract class Callback {
         /**
          * Called when the hotword availability changes.
          * This indicates a change in the availability of recognition for the given keyphrase.
@@ -278,7 +294,7 @@
          * @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_UNENROLLED
          * @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_ENROLLED
          */
-        void onAvailabilityChanged(int status);
+        public abstract void onAvailabilityChanged(int status);
         /**
          * Called when the keyphrase is spoken.
          * This implicitly stops listening for the keyphrase once it's detected.
@@ -289,23 +305,23 @@
          *        This may contain the trigger audio, if requested when calling
          *        {@link AlwaysOnHotwordDetector#startRecognition(int)}.
          */
-        void onDetected(@NonNull EventPayload eventPayload);
+        public abstract void onDetected(@NonNull EventPayload eventPayload);
         /**
          * Called when the detection fails due to an error.
          */
-        void onError();
+        public abstract void onError();
         /**
          * Called when the recognition is paused temporarily for some reason.
          * This is an informational callback, and the clients shouldn't be doing anything here
          * except showing an indication on their UI if they have to.
          */
-        void onRecognitionPaused();
+        public abstract void onRecognitionPaused();
         /**
          * Called when the recognition is resumed after it was temporarily paused.
          * This is an informational callback, and the clients shouldn't be doing anything here
          * except showing an indication on their UI if they have to.
          */
-        void onRecognitionResumed();
+        public abstract void onRecognitionResumed();
     }
 
     /**
@@ -372,10 +388,10 @@
     /**
      * Starts recognition for the associated keyphrase.
      *
+     * @see #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO
+     * @see #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS
+     *
      * @param recognitionFlags The flags to control the recognition properties.
-     *        The allowed flags are {@link #RECOGNITION_FLAG_NONE},
-     *        {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO} and
-     *        {@link #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS}.
      * @return Indicates whether the call succeeded or not.
      * @throws UnsupportedOperationException if the recognition isn't supported.
      *         Callers should only call this method after a supported state callback on
@@ -430,12 +446,13 @@
     }
 
     /**
-     * Gets an intent to manage the associated keyphrase.
+     * Creates an intent to start the enrollment for the associated keyphrase.
+     * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+     * Starting re-enrollment is only valid if the keyphrase is un-enrolled,
+     * i.e. {@link #STATE_KEYPHRASE_UNENROLLED},
+     * otherwise {@link #createIntentToReEnroll()} should be preferred.
      *
-     * @param action The manage action that needs to be performed.
-     *        One of {@link #MANAGE_ACTION_ENROLL}, {@link #MANAGE_ACTION_RE_ENROLL} or
-     *        {@link #MANAGE_ACTION_UN_ENROLL}.
-     * @return An {@link Intent} to manage the given keyphrase.
+     * @return An {@link Intent} to start enrollment for the given keyphrase.
      * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
      *         Callers should only call this method after a supported state callback on
      *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
@@ -443,10 +460,52 @@
      *         This may happen if another detector has been instantiated or the
      *         {@link VoiceInteractionService} hosting this detector has been shut down.
      */
-    public Intent getManageIntent(@ManageActions int action) {
-        if (DBG) Slog.d(TAG, "getManageIntent(" + action + ")");
+    public Intent createIntentToEnroll() {
+        if (DBG) Slog.d(TAG, "createIntentToEnroll");
         synchronized (mLock) {
-            return getManageIntentLocked(action);
+            return getManageIntentLocked(MANAGE_ACTION_ENROLL);
+        }
+    }
+
+    /**
+     * Creates an intent to start the un-enrollment for the associated keyphrase.
+     * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+     * Starting re-enrollment is only valid if the keyphrase is already enrolled,
+     * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error.
+     *
+     * @return An {@link Intent} to start un-enrollment for the given keyphrase.
+     * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
+     *         Callers should only call this method after a supported state callback on
+     *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
+     * @throws IllegalStateException if the detector is in an invalid state.
+     *         This may happen if another detector has been instantiated or the
+     *         {@link VoiceInteractionService} hosting this detector has been shut down.
+     */
+    public Intent createIntentToUnEnroll() {
+        if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
+        synchronized (mLock) {
+            return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
+        }
+    }
+
+    /**
+     * Creates an intent to start the re-enrollment for the associated keyphrase.
+     * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+     * Starting re-enrollment is only valid if the keyphrase is already enrolled,
+     * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error.
+     *
+     * @return An {@link Intent} to start re-enrollment for the given keyphrase.
+     * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
+     *         Callers should only call this method after a supported state callback on
+     *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
+     * @throws IllegalStateException if the detector is in an invalid state.
+     *         This may happen if another detector has been instantiated or the
+     *         {@link VoiceInteractionService} hosting this detector has been shut down.
+     */
+    public Intent createIntentToReEnroll() {
+        if (DBG) Slog.d(TAG, "createIntentToReEnroll");
+        synchronized (mLock) {
+            return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
         }
     }
 
@@ -462,12 +521,6 @@
                     "Managing the given keyphrase is not supported");
         }
 
-        if (action != MANAGE_ACTION_ENROLL
-                && action != MANAGE_ACTION_RE_ENROLL
-                && action != MANAGE_ACTION_UN_ENROLL) {
-            throw new IllegalArgumentException("Invalid action specified " + action);
-        }
-
         return mKeyphraseEnrollmentInfo.getManageKeyphraseIntent(action, mText, mLocale);
     }
 
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index aecf488..e82057c 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -262,6 +262,8 @@
             int fit = paraStart;
             float fitWidth = w;
             int fitAscent = 0, fitDescent = 0, fitTop = 0, fitBottom = 0;
+            // same as fitWidth but not including any trailing whitespace
+            float fitWidthGraphing = w;
 
             boolean hasTabOrEmoji = false;
             boolean hasTab = false;
@@ -346,6 +348,9 @@
 
                     if (w <= width || isSpaceOrTab) {
                         fitWidth = w;
+                        if (!isSpaceOrTab) {
+                            fitWidthGraphing = w;
+                        }
                         fit = j + 1;
 
                         if (fmTop < fitTop)
@@ -365,7 +370,7 @@
                                 breakOpp[breakOppIndex] == j - paraStart + 1;
 
                         if (isLineBreak) {
-                            okWidth = w;
+                            okWidth = fitWidthGraphing;
                             ok = j + 1;
 
                             if (fitTop < okTop)
@@ -426,6 +431,7 @@
                         j = here - 1; // restart j-span loop from here, compensating for the j++
                         ok = fit = here;
                         w = 0;
+                        fitWidthGraphing = w;
                         fitAscent = fitDescent = fitTop = fitBottom = 0;
                         okAscent = okDescent = okTop = okBottom = 0;
 
@@ -842,7 +848,7 @@
     void prepare() {
         mMeasured = MeasuredText.obtain();
     }
-    
+
     void finish() {
         mMeasured = MeasuredText.recycle(mMeasured);
     }
diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java
index ec79b36..3a63805 100644
--- a/core/java/android/text/format/TimeFormatter.java
+++ b/core/java/android/text/format/TimeFormatter.java
@@ -22,8 +22,7 @@
 
 import android.content.res.Resources;
 
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
+import java.nio.CharBuffer;
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -31,15 +30,13 @@
 import libcore.util.ZoneInfo;
 
 /**
- * Formatting logic for {@link Time}. Contains a port of Bionic's broken strftime_tz to Java. The
- * main issue with this implementation is the treatment of characters as ASCII, despite returning
- * localized (UTF-16) strings from the LocaleData.
+ * Formatting logic for {@link Time}. Contains a port of Bionic's broken strftime_tz to Java.
  *
  * <p>This class is not thread safe.
  */
 class TimeFormatter {
-    // An arbitrary value outside the range representable by a byte / ASCII character code.
-    private static final int FORCE_LOWER_CASE = 0x100;
+    // An arbitrary value outside the range representable by a char.
+    private static final int FORCE_LOWER_CASE = -1;
 
     private static final int SECSPERMIN = 60;
     private static final int MINSPERHOUR = 60;
@@ -62,10 +59,9 @@
     private final String dateTimeFormat;
     private final String timeOnlyFormat;
     private final String dateOnlyFormat;
-    private final Locale locale;
 
     private StringBuilder outputBuilder;
-    private Formatter outputFormatter;
+    private Formatter numberFormatter;
 
     public TimeFormatter() {
         synchronized (TimeFormatter.class) {
@@ -84,7 +80,6 @@
             this.dateTimeFormat = sDateTimeFormat;
             this.timeOnlyFormat = sTimeOnlyFormat;
             this.dateOnlyFormat = sDateOnlyFormat;
-            this.locale = locale;
             localeData = sLocaleData;
         }
     }
@@ -97,19 +92,21 @@
             StringBuilder stringBuilder = new StringBuilder();
 
             outputBuilder = stringBuilder;
-            outputFormatter = new Formatter(stringBuilder, locale);
+            // This uses the US locale because number localization is handled separately (see below)
+            // and locale sensitive strings are output directly using outputBuilder.
+            numberFormatter = new Formatter(stringBuilder, Locale.US);
 
             formatInternal(pattern, wallTime, zoneInfo);
             String result = stringBuilder.toString();
             // This behavior is the source of a bug since some formats are defined as being
-            // in ASCII. Generally localization is very broken.
+            // in ASCII and not localized.
             if (localeData.zeroDigit != '0') {
                 result = localizeDigits(result);
             }
             return result;
         } finally {
             outputBuilder = null;
-            outputFormatter = null;
+            numberFormatter = null;
         }
     }
 
@@ -132,38 +129,30 @@
      * {@link #outputBuilder}.
      */
     private void formatInternal(String pattern, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) {
-        // Convert to ASCII bytes to be compatible with old implementation behavior.
-        byte[] bytes = pattern.getBytes(StandardCharsets.US_ASCII);
-        if (bytes.length == 0) {
-            return;
-        }
-
-        ByteBuffer formatBuffer = ByteBuffer.wrap(bytes);
+        CharBuffer formatBuffer = CharBuffer.wrap(pattern);
         while (formatBuffer.remaining() > 0) {
-            boolean outputCurrentByte = true;
-            char currentByteAsChar = convertToChar(formatBuffer.get(formatBuffer.position()));
-            if (currentByteAsChar == '%') {
-                outputCurrentByte = handleToken(formatBuffer, wallTime, zoneInfo);
+            boolean outputCurrentChar = true;
+            char currentChar = formatBuffer.get(formatBuffer.position());
+            if (currentChar == '%') {
+                outputCurrentChar = handleToken(formatBuffer, wallTime, zoneInfo);
             }
-            if (outputCurrentByte) {
-                currentByteAsChar = convertToChar(formatBuffer.get(formatBuffer.position()));
-                outputBuilder.append(currentByteAsChar);
+            if (outputCurrentChar) {
+                outputBuilder.append(formatBuffer.get(formatBuffer.position()));
             }
-
             formatBuffer.position(formatBuffer.position() + 1);
         }
     }
 
-    private boolean handleToken(ByteBuffer formatBuffer, ZoneInfo.WallTime wallTime,
+    private boolean handleToken(CharBuffer formatBuffer, ZoneInfo.WallTime wallTime,
             ZoneInfo zoneInfo) {
 
-        // The byte at formatBuffer.position() is expected to be '%' at this point.
+        // The char at formatBuffer.position() is expected to be '%' at this point.
         int modifier = 0;
         while (formatBuffer.remaining() > 1) {
-            // Increment the position then get the new current byte.
+            // Increment the position then get the new current char.
             formatBuffer.position(formatBuffer.position() + 1);
-            char currentByteAsChar = convertToChar(formatBuffer.get(formatBuffer.position()));
-            switch (currentByteAsChar) {
+            char currentChar = formatBuffer.get(formatBuffer.position());
+            switch (currentChar) {
                 case 'A':
                     modifyAndAppend((wallTime.getWeekDay() < 0
                                     || wallTime.getWeekDay() >= DAYSPERWEEK)
@@ -206,7 +195,7 @@
                     formatInternal("%m/%d/%y", wallTime, zoneInfo);
                     return false;
                 case 'd':
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
                             wallTime.getMonthDay());
                     return false;
                 case 'E':
@@ -218,46 +207,46 @@
                 case '0':
                 case '^':
                 case '#':
-                    modifier = currentByteAsChar;
+                    modifier = currentChar;
                     continue;
                 case 'e':
-                    outputFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"),
                             wallTime.getMonthDay());
                     return false;
                 case 'F':
                     formatInternal("%Y-%m-%d", wallTime, zoneInfo);
                     return false;
                 case 'H':
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
                             wallTime.getHour());
                     return false;
                 case 'I':
                     int hour = (wallTime.getHour() % 12 != 0) ? (wallTime.getHour() % 12) : 12;
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), hour);
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), hour);
                     return false;
                 case 'j':
                     int yearDay = wallTime.getYearDay() + 1;
-                    outputFormatter.format(getFormat(modifier, "%03d", "%3d", "%d", "%03d"),
+                    numberFormatter.format(getFormat(modifier, "%03d", "%3d", "%d", "%03d"),
                             yearDay);
                     return false;
                 case 'k':
-                    outputFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"),
                             wallTime.getHour());
                     return false;
                 case 'l':
                     int n2 = (wallTime.getHour() % 12 != 0) ? (wallTime.getHour() % 12) : 12;
-                    outputFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), n2);
+                    numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), n2);
                     return false;
                 case 'M':
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
                             wallTime.getMinute());
                     return false;
                 case 'm':
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
                             wallTime.getMonth() + 1);
                     return false;
                 case 'n':
-                    modifyAndAppend("\n", modifier);
+                    outputBuilder.append('\n');
                     return false;
                 case 'p':
                     modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) ? localeData.amPm[1]
@@ -274,27 +263,27 @@
                     formatInternal("%I:%M:%S %p", wallTime, zoneInfo);
                     return false;
                 case 'S':
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
                             wallTime.getSecond());
                     return false;
                 case 's':
                     int timeInSeconds = wallTime.mktime(zoneInfo);
-                    modifyAndAppend(Integer.toString(timeInSeconds), modifier);
+                    outputBuilder.append(Integer.toString(timeInSeconds));
                     return false;
                 case 'T':
                     formatInternal("%H:%M:%S", wallTime, zoneInfo);
                     return false;
                 case 't':
-                    modifyAndAppend("\t", modifier);
+                    outputBuilder.append('\t');
                     return false;
                 case 'U':
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
                             (wallTime.getYearDay() + DAYSPERWEEK - wallTime.getWeekDay())
                                     / DAYSPERWEEK);
                     return false;
                 case 'u':
                     int day = (wallTime.getWeekDay() == 0) ? DAYSPERWEEK : wallTime.getWeekDay();
-                    outputFormatter.format("%d", day);
+                    numberFormatter.format("%d", day);
                     return false;
                 case 'V':   /* ISO 8601 week number */
                 case 'G':   /* ISO 8601 year (four digits) */
@@ -326,9 +315,9 @@
                         --year;
                         yday += isLeap(year) ? DAYSPERLYEAR : DAYSPERNYEAR;
                     }
-                    if (currentByteAsChar == 'V') {
-                        outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), w);
-                    } else if (currentByteAsChar == 'g') {
+                    if (currentChar == 'V') {
+                        numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), w);
+                    } else if (currentChar == 'g') {
                         outputYear(year, false, true, modifier);
                     } else {
                         outputYear(year, true, true, modifier);
@@ -342,10 +331,10 @@
                     int n = (wallTime.getYearDay() + DAYSPERWEEK - (
                                     wallTime.getWeekDay() != 0 ? (wallTime.getWeekDay() - 1)
                                             : (DAYSPERWEEK - 1))) / DAYSPERWEEK;
-                    outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n);
+                    numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n);
                     return false;
                 case 'w':
-                    outputFormatter.format("%d", wallTime.getWeekDay());
+                    numberFormatter.format("%d", wallTime.getWeekDay());
                     return false;
                 case 'X':
                     formatInternal(timeOnlyFormat, wallTime, zoneInfo);
@@ -371,17 +360,17 @@
                         return false;
                     }
                     int diff = wallTime.getGmtOffset();
-                    String sign;
+                    char sign;
                     if (diff < 0) {
-                        sign = "-";
+                        sign = '-';
                         diff = -diff;
                     } else {
-                        sign = "+";
+                        sign = '+';
                     }
-                    modifyAndAppend(sign, modifier);
+                    outputBuilder.append(sign);
                     diff /= SECSPERMIN;
                     diff = (diff / MINSPERHOUR) * 100 + (diff % MINSPERHOUR);
-                    outputFormatter.format(getFormat(modifier, "%04d", "%4d", "%d", "%04d"), diff);
+                    numberFormatter.format(getFormat(modifier, "%04d", "%4d", "%d", "%04d"), diff);
                     return false;
                 }
                 case '+':
@@ -422,7 +411,6 @@
                 break;
             default:
                 outputBuilder.append(str);
-
         }
     }
 
@@ -443,14 +431,14 @@
         }
         if (outputTop) {
             if (lead == 0 && trail < 0) {
-                modifyAndAppend("-0", modifier);
+                outputBuilder.append("-0");
             } else {
-                outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), lead);
+                numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), lead);
             }
         }
         if (outputBottom) {
             int n = ((trail < 0) ? -trail : trail);
-            outputFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n);
+            numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n);
         }
     }
 
@@ -472,24 +460,24 @@
     }
 
     /**
-     * A broken implementation of {@link Character#isUpperCase(char)} that assumes ASCII in order to
-     * be compatible with the old native implementation.
+     * A broken implementation of {@link Character#isUpperCase(char)} that assumes ASCII codes in
+     * order to be compatible with the old native implementation.
      */
     private static boolean brokenIsUpper(char toCheck) {
         return toCheck >= 'A' && toCheck <= 'Z';
     }
 
     /**
-     * A broken implementation of {@link Character#isLowerCase(char)} that assumes ASCII in order to
-     * be compatible with the old native implementation.
+     * A broken implementation of {@link Character#isLowerCase(char)} that assumes ASCII codes in
+     * order to be compatible with the old native implementation.
      */
     private static boolean brokenIsLower(char toCheck) {
         return toCheck >= 'a' && toCheck <= 'z';
     }
 
     /**
-     * A broken implementation of {@link Character#toLowerCase(char)} that assumes ASCII in order to
-     * be compatible with the old native implementation.
+     * A broken implementation of {@link Character#toLowerCase(char)} that assumes ASCII codes in
+     * order to be compatible with the old native implementation.
      */
     private static char brokenToLower(char input) {
         if (input >= 'A' && input <= 'Z') {
@@ -499,8 +487,8 @@
     }
 
     /**
-     * A broken implementation of {@link Character#toUpperCase(char)} that assumes ASCII in order to
-     * be compatible with the old native implementation.
+     * A broken implementation of {@link Character#toUpperCase(char)} that assumes ASCII codes in
+     * order to be compatible with the old native implementation.
      */
     private static char brokenToUpper(char input) {
         if (input >= 'a' && input <= 'z') {
@@ -509,11 +497,4 @@
         return input;
     }
 
-    /**
-     * Safely convert a byte containing an ASCII character to a char, even for character codes
-     * > 127.
-     */
-    private static char convertToChar(byte b) {
-        return (char) (b & 0xFF);
-    }
 }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 59ba71f..bd52e71 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1656,7 +1656,7 @@
                 WindowId windowId = sceneRoot.getWindowId();
                 for (int i = numOldAnims - 1; i >= 0; i--) {
                     AnimationInfo info = runningAnimators.valueAt(i);
-                    if (info.view != null && windowId.equals(info.windowId)) {
+                    if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
                         Animator anim = runningAnimators.keyAt(i);
                         anim.pause();
                     }
@@ -1689,7 +1689,7 @@
                 WindowId windowId = sceneRoot.getWindowId();
                 for (int i = numOldAnims - 1; i >= 0; i--) {
                     AnimationInfo info = runningAnimators.valueAt(i);
-                    if (info.view != null && windowId.equals(info.windowId)) {
+                    if (info.view != null && windowId != null && windowId.equals(info.windowId)) {
                         Animator anim = runningAnimators.keyAt(i);
                         anim.resume();
                     }
diff --git a/core/java/android/util/Size.java b/core/java/android/util/Size.java
index d58f778..6424344 100644
--- a/core/java/android/util/Size.java
+++ b/core/java/android/util/Size.java
@@ -16,12 +16,15 @@
 
 package android.util;
 
-import static com.android.internal.util.Preconditions.*;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * Immutable class for describing width and height dimensions in pixels.
  */
-public final class Size {
+public final class Size implements Parcelable {
     /**
      * Create a new immutable Size instance.
      *
@@ -33,6 +36,11 @@
         mHeight = height;
     }
 
+    private Size(Parcel in) {
+        mWidth = in.readInt();
+        mHeight = in.readInt();
+    }
+
     /**
      * Get the width of the size (in pixels).
      * @return width
@@ -147,6 +155,29 @@
         return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
     }
 
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mWidth);
+        out.writeInt(mHeight);
+    }
+
+    public static final Parcelable.Creator<Size> CREATOR = new Parcelable.Creator<Size>() {
+        @Override
+        public Size createFromParcel(Parcel in) {
+            return new Size(in);
+        }
+
+        @Override
+        public Size[] newArray(int size) {
+            return new Size[size];
+        }
+    };
+
     private final int mWidth;
     private final int mHeight;
-};
+}
diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java
index 0a8b4ed..88bb4393 100644
--- a/core/java/android/util/SizeF.java
+++ b/core/java/android/util/SizeF.java
@@ -16,7 +16,10 @@
 
 package android.util;
 
-import static com.android.internal.util.Preconditions.*;
+import static com.android.internal.util.Preconditions.checkArgumentFinite;
+
+import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * Immutable class for describing width and height dimensions in some arbitrary
@@ -25,7 +28,7 @@
  * Width and height are finite values stored as a floating point representation.
  * </p>
  */
-public final class SizeF {
+public final class SizeF implements Parcelable {
     /**
      * Create a new immutable SizeF instance.
      *
@@ -43,6 +46,11 @@
         mHeight = checkArgumentFinite(height, "height");
     }
 
+    private SizeF(Parcel in) {
+        mWidth = in.readFloat();
+        mHeight = in.readFloat();
+    }
+
     /**
      * Get the width of the size (as an arbitrary unit).
      * @return width
@@ -103,6 +111,29 @@
         return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
     }
 
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeFloat(mWidth);
+        out.writeFloat(mHeight);
+    }
+
+    public static final Parcelable.Creator<SizeF> CREATOR = new Parcelable.Creator<SizeF>() {
+        @Override
+        public SizeF createFromParcel(Parcel in) {
+            return new SizeF(in);
+        }
+
+        @Override
+        public SizeF[] newArray(int size) {
+            return new SizeF[size];
+        }
+    };
+
     private final float mWidth;
     private final float mHeight;
-};
+}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index de90899..edb3798 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -485,4 +485,6 @@
      * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
      */
     abstract void notifyFramePending();
+
+    abstract void registerAnimatingRenderNode(RenderNode animator);
 }
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 099f153..9dc9766 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -167,10 +167,13 @@
     public static final int STATUS_DREW = 0x4;
 
     private boolean mValid;
-    private final long mNativeRenderNode;
+    // Do not access directly unless you are ThreadedRenderer
+    final long mNativeRenderNode;
+    private final View mOwningView;
 
-    private RenderNode(String name) {
+    private RenderNode(String name, View owningView) {
         mNativeRenderNode = nCreate(name);
+        mOwningView = owningView;
     }
 
     /**
@@ -178,6 +181,7 @@
      */
     private RenderNode(long nativePtr) {
         mNativeRenderNode = nativePtr;
+        mOwningView = null;
     }
 
     /**
@@ -188,8 +192,8 @@
      *
      * @return A new RenderNode.
      */
-    public static RenderNode create(String name) {
-        return new RenderNode(name);
+    public static RenderNode create(String name, @Nullable View owningView) {
+        return new RenderNode(name, owningView);
     }
 
     /**
@@ -805,7 +809,15 @@
     ///////////////////////////////////////////////////////////////////////////
 
     public void addAnimator(RenderNodeAnimator animator) {
+        if (mOwningView == null || mOwningView.mAttachInfo == null) {
+            throw new IllegalStateException("Cannot start this animator on a detached view!");
+        }
         nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
+        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
+    }
+
+    public void endAllAnimators() {
+        nEndAllAnimators(mNativeRenderNode);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -891,6 +903,7 @@
     ///////////////////////////////////////////////////////////////////////////
 
     private static native void nAddAnimator(long renderNode, long animatorPtr);
+    private static native void nEndAllAnimators(long renderNode);
 
     ///////////////////////////////////////////////////////////////////////////
     // Finalization
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 9433237..fa4a13a 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,7 +19,6 @@
 import android.animation.Animator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.animation.Animator.AnimatorListener;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
@@ -30,7 +29,6 @@
 import com.android.internal.view.animation.HasNativeInterpolator;
 import com.android.internal.view.animation.NativeInterpolatorFactory;
 
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 /**
@@ -89,8 +87,11 @@
     private float mFinalValue;
     private TimeInterpolator mInterpolator;
 
-    private boolean mStarted = false;
-    private boolean mFinished = false;
+    private static final int STATE_PREPARE = 0;
+    private static final int STATE_DELAYED = 1;
+    private static final int STATE_RUNNING = 2;
+    private static final int STATE_FINISHED = 3;
+    private int mState = STATE_PREPARE;
 
     private long mUnscaledDuration = 300;
     private long mUnscaledStartDelay = 0;
@@ -111,13 +112,11 @@
         mRenderProperty = property;
         mFinalValue = finalValue;
         mUiThreadHandlesDelay = true;
-        init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
-                property, finalValue));
+        init(nCreateAnimator(property, finalValue));
     }
 
     public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) {
         init(nCreateCanvasPropertyFloatAnimator(
-                new WeakReference<RenderNodeAnimator>(this),
                 property.getNativeContainer(), finalValue));
         mUiThreadHandlesDelay = false;
     }
@@ -132,14 +131,12 @@
      */
     public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) {
         init(nCreateCanvasPropertyPaintAnimator(
-                new WeakReference<RenderNodeAnimator>(this),
                 property.getNativeContainer(), paintField, finalValue));
         mUiThreadHandlesDelay = false;
     }
 
     public RenderNodeAnimator(int x, int y, float startRadius, float endRadius) {
-        init(nCreateRevealAnimator(new WeakReference<RenderNodeAnimator>(this),
-                x, y, startRadius, endRadius));
+        init(nCreateRevealAnimator(x, y, startRadius, endRadius));
         mUiThreadHandlesDelay = true;
     }
 
@@ -148,7 +145,7 @@
     }
 
     private void checkMutable() {
-        if (mStarted) {
+        if (mState != STATE_PREPARE) {
             throw new IllegalStateException("Animator has already started, cannot change it now!");
         }
     }
@@ -176,11 +173,11 @@
             throw new IllegalStateException("Missing target!");
         }
 
-        if (mStarted) {
+        if (mState != STATE_PREPARE) {
             throw new IllegalStateException("Already started!");
         }
 
-        mStarted = true;
+        mState = STATE_DELAYED;
         applyInterpolator();
 
         if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
@@ -192,7 +189,8 @@
     }
 
     private void doStart() {
-        nStart(mNativePtr.get());
+        mState = STATE_RUNNING;
+        nStart(mNativePtr.get(), this);
 
         // Alpha is a special snowflake that has the canonical value stored
         // in mTransformationInfo instead of in RenderNode, so we need to update
@@ -203,11 +201,7 @@
             mViewTarget.mTransformationInfo.mAlpha = mFinalValue;
         }
 
-        final ArrayList<AnimatorListener> listeners = cloneListeners();
-        final int numListeners = listeners == null ? 0 : listeners.size();
-        for (int i = 0; i < numListeners; i++) {
-            listeners.get(i).onAnimationStart(this);
-        }
+        notifyStartListeners();
 
         if (mViewTarget != null) {
             // Kick off a frame to start the process
@@ -215,10 +209,21 @@
         }
     }
 
+    private void notifyStartListeners() {
+        final ArrayList<AnimatorListener> listeners = cloneListeners();
+        final int numListeners = listeners == null ? 0 : listeners.size();
+        for (int i = 0; i < numListeners; i++) {
+            listeners.get(i).onAnimationStart(this);
+        }
+    }
+
     @Override
     public void cancel() {
-        if (!mFinished) {
-            getHelper().removeDelayedAnimation(this);
+        if (mState != STATE_FINISHED) {
+            if (mState == STATE_DELAYED) {
+                getHelper().removeDelayedAnimation(this);
+                notifyStartListeners();
+            }
             nEnd(mNativePtr.get());
 
             final ArrayList<AnimatorListener> listeners = cloneListeners();
@@ -226,12 +231,17 @@
             for (int i = 0; i < numListeners; i++) {
                 listeners.get(i).onAnimationCancel(this);
             }
+
+            if (mViewTarget != null) {
+                // Kick off a frame to flush the state change
+                mViewTarget.invalidateViewProperty(true, false);
+            }
         }
     }
 
     @Override
     public void end() {
-        if (!mFinished) {
+        if (mState != STATE_FINISHED) {
             nEnd(mNativePtr.get());
         }
     }
@@ -248,24 +258,21 @@
 
     public void setTarget(View view) {
         mViewTarget = view;
-        mTarget = view.mRenderNode;
-        mTarget.addAnimator(this);
+        setTarget(mViewTarget.mRenderNode);
     }
 
     public void setTarget(Canvas canvas) {
         if (!(canvas instanceof GLES20RecordingCanvas)) {
             throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
         }
-
         final GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
         setTarget(recordingCanvas.mNode);
     }
 
-    public void setTarget(RenderNode node) {
+    private void setTarget(RenderNode node) {
         if (mTarget != null) {
             throw new IllegalStateException("Target already set!");
         }
-        mViewTarget = null;
         mTarget = node;
         mTarget.addAnimator(this);
     }
@@ -308,12 +315,12 @@
 
     @Override
     public boolean isRunning() {
-        return mStarted && !mFinished;
+        return mState == STATE_DELAYED || mState == STATE_RUNNING;
     }
 
     @Override
     public boolean isStarted() {
-        return mStarted;
+        return mState != STATE_PREPARE;
     }
 
     @Override
@@ -328,13 +335,23 @@
     }
 
     protected void onFinished() {
-        mFinished = true;
+        if (mState == STATE_DELAYED) {
+            getHelper().removeDelayedAnimation(this);
+            notifyStartListeners();
+        }
+        mState = STATE_FINISHED;
 
         final ArrayList<AnimatorListener> listeners = cloneListeners();
         final int numListeners = listeners == null ? 0 : listeners.size();
         for (int i = 0; i < numListeners; i++) {
             listeners.get(i).onAnimationEnd(this);
         }
+
+        // Release the native object, as it has a global reference to us. This
+        // breaks the cyclic reference chain, and allows this object to be
+        // GC'd
+        mNativePtr.release();
+        mNativePtr = null;
     }
 
     @SuppressWarnings("unchecked")
@@ -427,11 +444,8 @@
     }
 
     // Called by native
-    private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) {
-        RenderNodeAnimator animator = weakThis.get();
-        if (animator != null) {
-            animator.onFinished();
-        }
+    private static void callOnFinished(RenderNodeAnimator animator) {
+        animator.onFinished();
     }
 
     @Override
@@ -439,22 +453,20 @@
         throw new IllegalStateException("Cannot clone this animator");
     }
 
-    private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            int property, float finalValue);
-    private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
+    private static native long nCreateAnimator(int property, float finalValue);
+    private static native long nCreateCanvasPropertyFloatAnimator(
             long canvasProperty, float finalValue);
-    private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
+    private static native long nCreateCanvasPropertyPaintAnimator(
             long canvasProperty, int paintField, float finalValue);
-    private static native long nCreateRevealAnimator(WeakReference<RenderNodeAnimator> weakThis,
+    private static native long nCreateRevealAnimator(
             int x, int y, float startRadius, float endRadius);
 
     private static native void nSetStartValue(long nativePtr, float startValue);
     private static native void nSetDuration(long nativePtr, long duration);
     private static native long nGetDuration(long nativePtr);
     private static native void nSetStartDelay(long nativePtr, long startDelay);
-    private static native long nGetStartDelay(long nativePtr);
     private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
 
-    private static native void nStart(long animPtr);
+    private static native void nStart(long animPtr, RenderNodeAnimator finishListener);
     private static native void nEnd(long animPtr);
 }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 3af214d..ca08ecc 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -277,7 +277,11 @@
                 final int saveCount = canvas.save();
                 canvas.translate(mInsetLeft, mInsetTop);
                 callbacks.onHardwarePreDraw(canvas);
+
+                canvas.insertReorderBarrier();
                 canvas.drawRenderNode(view.getDisplayList());
+                canvas.insertInorderBarrier();
+
                 callbacks.onHardwarePostDraw(canvas);
                 canvas.restoreToCount(saveCount);
                 mRootNodeNeedsUpdate = false;
@@ -312,6 +316,20 @@
 
         attachInfo.mIgnoreDirtyState = false;
 
+        // register animating rendernodes which started animating prior to renderer
+        // creation, which is typical for animators started prior to first draw
+        if (attachInfo.mPendingAnimatingRenderNodes != null) {
+            final int count = attachInfo.mPendingAnimatingRenderNodes.size();
+            for (int i = 0; i < count; i++) {
+                registerAnimatingRenderNode(
+                        attachInfo.mPendingAnimatingRenderNodes.get(i));
+            }
+            attachInfo.mPendingAnimatingRenderNodes.clear();
+            // We don't need this anymore as subsequent calls to
+            // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
+            attachInfo.mPendingAnimatingRenderNodes = null;
+        }
+
         int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
                 recordDuration, view.getResources().getDisplayMetrics().density);
         if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
@@ -370,6 +388,11 @@
     }
 
     @Override
+    void registerAnimatingRenderNode(RenderNode animator) {
+        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
+    }
+
+    @Override
     protected void finalize() throws Throwable {
         try {
             nDeleteProxy(mNativeProxy);
@@ -466,6 +489,7 @@
     private static native int nSyncAndDrawFrame(long nativeProxy,
             long frameTimeNanos, long recordDuration, float density);
     private static native void nDestroyCanvasAndSurface(long nativeProxy);
+    private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
 
     private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2d58ecf..fce6f0b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3565,7 +3565,7 @@
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
         mUserPaddingStart = UNDEFINED_PADDING;
         mUserPaddingEnd = UNDEFINED_PADDING;
-        mRenderNode = RenderNode.create(getClass().getName());
+        mRenderNode = RenderNode.create(getClass().getName(), this);
 
         if (!sCompatibilityDone && context != null) {
             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -4161,7 +4161,7 @@
      */
     View() {
         mResources = null;
-        mRenderNode = RenderNode.create(getClass().getName());
+        mRenderNode = RenderNode.create(getClass().getName(), this);
     }
 
     private static SparseArray<String> getAttributeMap() {
@@ -15183,9 +15183,9 @@
      * @param renderNode Existing RenderNode, or {@code null}
      * @return A valid display list for the specified drawable
      */
-    private static RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
+    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
         if (renderNode == null) {
-            renderNode = RenderNode.create(drawable.getClass().getName());
+            renderNode = RenderNode.create(drawable.getClass().getName(), this);
         }
 
         final Rect bounds = drawable.getBounds();
@@ -19911,6 +19911,7 @@
         boolean mHardwareAccelerated;
         boolean mHardwareAccelerationRequested;
         HardwareRenderer mHardwareRenderer;
+        List<RenderNode> mPendingAnimatingRenderNodes;
 
         /**
          * The state of the display to which the window is attached, as reported
@@ -20691,6 +20692,7 @@
             if (mPosted) {
                 return;
             }
+
             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
             final long minEventIntevalMillis =
                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
@@ -20699,7 +20701,6 @@
                 run();
             } else {
                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
-                mPosted = true;
                 mPostedWithDelay = true;
             }
         }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index bae0cfb..b73b9fa 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -430,6 +430,10 @@
             }
         }
         mPendingAnimations.clear();
+        mPendingSetupAction = null;
+        mPendingCleanupAction = null;
+        mPendingOnStartAction = null;
+        mPendingOnEndAction = null;
         mView.removeCallbacks(mAnimationStarter);
         if (mRTBackend != null) {
             mRTBackend.cancelAll();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bb469a3..49d925f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -333,6 +333,8 @@
     private boolean mRemoved;
 
     private boolean mIsEmulator;
+    private boolean mIsCircularEmulator;
+    private final boolean mWindowIsRound;
 
     /**
      * Consistency verifier for debugging purposes.
@@ -388,6 +390,8 @@
         mChoreographer = Choreographer.getInstance();
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
         loadSystemProperties();
+        mWindowIsRound = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_windowIsRound);
     }
 
     public static void addFirstDrawHandler(Runnable callback) {
@@ -671,6 +675,17 @@
         ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
     }
 
+    public void registerAnimatingRenderNode(RenderNode animator) {
+        if (mAttachInfo.mHardwareRenderer != null) {
+            mAttachInfo.mHardwareRenderer.registerAnimatingRenderNode(animator);
+        } else {
+            if (mAttachInfo.mPendingAnimatingRenderNodes == null) {
+                mAttachInfo.mPendingAnimatingRenderNodes = new ArrayList<RenderNode>();
+            }
+            mAttachInfo.mPendingAnimatingRenderNodes.add(animator);
+        }
+    }
+
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
@@ -1183,14 +1198,7 @@
     void dispatchApplyInsets(View host) {
         mDispatchContentInsets.set(mAttachInfo.mContentInsets);
         mDispatchStableInsets.set(mAttachInfo.mStableInsets);
-        boolean isRound = false;
-        if ((mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) != 0
-                && mDisplay.getDisplayId() == 0) {
-            // we're fullscreen and not hosted in an ActivityView
-            isRound = (mIsEmulator && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))
-                    || mContext.getResources().getBoolean(
-                            com.android.internal.R.bool.config_windowIsRound);
-        }
+        final boolean isRound = (mIsEmulator && mIsCircularEmulator) || mWindowIsRound;
         host.dispatchApplyWindowInsets(new WindowInsets(
                 mDispatchContentInsets, null /* windowDecorInsets */,
                 mDispatchStableInsets, isRound));
@@ -2329,6 +2337,16 @@
             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
         }
 
+        // For whatever reason we didn't create a HardwareRenderer, end any
+        // hardware animations that are now dangling
+        if (mAttachInfo.mPendingAnimatingRenderNodes != null) {
+            final int count = mAttachInfo.mPendingAnimatingRenderNodes.size();
+            for (int i = 0; i < count; i++) {
+                mAttachInfo.mPendingAnimatingRenderNodes.get(i).endAllAnimators();
+            }
+            mAttachInfo.mPendingAnimatingRenderNodes.clear();
+        }
+
         if (mReportNextDraw) {
             mReportNextDraw = false;
             if (mAttachInfo.mHardwareRenderer != null) {
@@ -5431,6 +5449,8 @@
 
                 // detect emulator
                 mIsEmulator = Build.HARDWARE.contains("goldfish");
+                mIsCircularEmulator =
+                        SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false);
             }
         });
     }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 2c7ea3e..9b6f200 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1304,12 +1304,22 @@
     public abstract int getVolumeControlStream();
 
     /**
+     * Sets a {@link MediaController} to send media keys and volume changes to.
+     * If set, this should be preferred for all media keys and volume requests
+     * sent to this window.
+     *
+     * @param controller The controller for the session which should receive
+     *            media keys and volume changes.
      * @see android.app.Activity#setMediaController(android.media.session.MediaController)
      */
     public void setMediaController(MediaController controller) {
     }
 
     /**
+     * Gets the {@link MediaController} that was previously set.
+     *
+     * @return The controller which should receive events.
+     * @see #setMediaController(android.media.session.MediaController)
      * @see android.app.Activity#getMediaController()
      */
     public MediaController getMediaController() {
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
index 862e8c2..6ad639c 100644
--- a/core/java/android/webkit/PermissionRequest.java
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -19,8 +19,10 @@
 import android.net.Uri;
 
 /**
- * This interface defines a permission request and is used when web content
- * requests access to protected resources.
+ * This class defines a permission request and is used when web content
+ * requests access to protected resources. The permission request related events
+ * are delivered via {@link WebChromeClient#onPermissionRequest} and
+ * {@link WebChromeClient#onPermissionRequestCanceled}.
  *
  * Either {@link #grant(String[]) grant()} or {@link #deny()} must be called in UI
  * thread to respond to the request.
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 35c9598..547acfa 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -452,14 +452,16 @@
      */
     public static abstract class FileChooserParams {
         /** Open single file. Requires that the file exists before allowing the user to pick it. */
-        public static final int OPEN = 0;
+        public static final int MODE_OPEN = 0;
         /** Like Open but allows multiple files to be selected. */
-        public static final int OPEN_MULTIPLE = 1;
+        public static final int MODE_OPEN_MULTIPLE = 1;
         /** Like Open but allows a folder to be selected. The implementation should enumerate
-            all files selected by this operation. */
-        public static final int OPEN_FOLDER = 2;
+            all files selected by this operation.
+            This feature is not supported at the moment.
+            @hide */
+        public static final int MODE_OPEN_FOLDER = 2;
         /**  Allows picking a nonexistent file and saving it. */
-        public static final int SAVE = 3;
+        public static final int MODE_SAVE = 3;
 
         /**
          * Returns a helper to simplify choosing and uploading files. The helper builds a default
@@ -474,7 +476,8 @@
         public abstract int getMode();
 
         /**
-         * Returns an array of acceptable MIME types. The array will be empty if no
+         * Returns an array of acceptable MIME types. The returned MIME type
+         * could be partial such as audio/*. The array will be empty if no
          * acceptable types are specified.
          */
         public abstract String[] getAcceptTypes();
@@ -494,9 +497,9 @@
         public abstract CharSequence getTitle();
 
         /**
-         * The file path of a default selection if specified, or null.
+         * The file name of a default selection if specified, or null.
          */
-        public abstract String getDefaultFilename();
+        public abstract String getFilenameHint();
     };
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1b0cb3d..e1f19ee 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1624,10 +1624,18 @@
     }
 
     /**
-     * Enable drawing the entire HTML document at a significant performance
-     * cost. Call this to enable drawing and capturing HTML content outside of
-     * the WebView's viewport. This should be called before any WebViews are
-     * created.
+     * For apps targeting the L release, WebView has a new default behavior that reduces
+     * memory footprint and increases performance by intelligently choosing
+     * the portion of the HTML document that needs to be drawn. These
+     * optimizations are transparent to the developers. However, under certain
+     * circumstances, an App developer may want to disable them:
+     * 1. When an app uses {@link #onDraw} to do own drawing and accesses portions
+     * of the page that is way outside the visible portion of the page.
+     * 2. When an app uses {@link #capturePicture} to capture a very large HTML document.
+     * Note that capturePicture is a deprecated API.
+     *
+     * Enabling drawing the entire HTML document has a significant performance
+     * cost. This method should be called before any WebViews are created.
      */
     public static void enableSlowWholeDocumentDraw() {
         getFactory().getStatics().enableSlowWholeDocumentDraw();
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 7123b9a..ef8c006 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseBooleanArray;
@@ -645,6 +647,23 @@
             super.onInitializeAccessibilityNodeInfo(info);
             info.setCanOpenPopup(true);
         }
+
+        @Override
+        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+            super.onLayout(changed, left, top, right, bottom);
+
+            // Set up the hotspot bounds to be centered on the image.
+            final Drawable d = getDrawable();
+            final Drawable bg = getBackground();
+            if (d != null && bg != null) {
+                final Rect bounds = d.getBounds();
+                final int height = bottom - top;
+                final int offset = (height - bounds.width()) / 2;
+                final int hotspotLeft = bounds.left - offset;
+                final int hotspotRight = bounds.right + offset;
+                bg.setHotspotBounds(hotspotLeft, 0, hotspotRight, height);
+            }
+        }
     }
 
     private class OverflowPopup extends MenuPopupHelper {
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index eb232fd..3b16aba 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -35,9 +35,8 @@
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
-
 import com.android.internal.R;
-
+import java.lang.ref.WeakReference;
 
 /**
  * <p>An editable text view that shows completion suggestions automatically
@@ -85,8 +84,8 @@
  * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor
  * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
  * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
- * @attr ref android.R.styleable#AutoCompleteTextView_dropDownVerticalOffset
- * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHorizontalOffset
+ * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
+ * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
  */
 public class AutoCompleteTextView extends EditText implements Filter.FilterListener {
     static final boolean DEBUG = false;
@@ -130,7 +129,7 @@
     }
 
     public AutoCompleteTextView(Context context, AttributeSet attrs) {
-        this(context, attrs, com.android.internal.R.attr.autoCompleteTextViewStyle);
+        this(context, attrs, R.attr.autoCompleteTextViewStyle);
     }
 
     public AutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -141,23 +140,17 @@
             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
-        mPopup = new ListPopupWindow(context, attrs,
-                com.android.internal.R.attr.autoCompleteTextViewStyle);
+        mPopup = new ListPopupWindow(context, attrs, defStyleAttr, defStyleRes);
         mPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
         mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW);
 
-        final TypedArray a = context.obtainStyledAttributes(attrs,
-                com.android.internal.R.styleable.AutoCompleteTextView, defStyleAttr, defStyleRes);
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.AutoCompleteTextView, defStyleAttr, defStyleRes);
 
-        mThreshold = a.getInt(
-                R.styleable.AutoCompleteTextView_completionThreshold, 2);
+        mThreshold = a.getInt(R.styleable.AutoCompleteTextView_completionThreshold, 2);
 
         mPopup.setListSelector(a.getDrawable(R.styleable.AutoCompleteTextView_dropDownSelector));
-        mPopup.setVerticalOffset((int)
-                a.getDimension(R.styleable.AutoCompleteTextView_dropDownVerticalOffset, 0.0f));
-        mPopup.setHorizontalOffset((int)
-                a.getDimension(R.styleable.AutoCompleteTextView_dropDownHorizontalOffset, 0.0f));
-        
+
         // Get the anchor's id now, but the view won't be ready, so wait to actually get the
         // view and store it in mDropDownAnchorView lazily in getDropDownAnchorView later.
         // Defaults to NO_ID, in which case the getDropDownAnchorView method will simply return
@@ -167,11 +160,9 @@
         
         // For dropdown width, the developer can specify a specific width, or MATCH_PARENT
         // (for full screen width) or WRAP_CONTENT (to match the width of the anchored view).
-        mPopup.setWidth(a.getLayoutDimension(
-                R.styleable.AutoCompleteTextView_dropDownWidth,
+        mPopup.setWidth(a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownWidth,
                 ViewGroup.LayoutParams.WRAP_CONTENT));
-        mPopup.setHeight(a.getLayoutDimension(
-                R.styleable.AutoCompleteTextView_dropDownHeight,
+        mPopup.setHeight(a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownHeight,
                 ViewGroup.LayoutParams.WRAP_CONTENT));
 
         mHintResource = a.getResourceId(R.styleable.AutoCompleteTextView_completionHintView,
@@ -373,6 +364,8 @@
      * <p>Sets the vertical offset used for the auto-complete drop-down list.</p>
      * 
      * @param offset the vertical offset
+     *
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
      */
     public void setDropDownVerticalOffset(int offset) {
         mPopup.setVerticalOffset(offset);
@@ -382,6 +375,8 @@
      * <p>Gets the vertical offset used for the auto-complete drop-down list.</p>
      * 
      * @return the vertical offset
+     *
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
      */
     public int getDropDownVerticalOffset() {
         return mPopup.getVerticalOffset();
@@ -391,6 +386,8 @@
      * <p>Sets the horizontal offset used for the auto-complete drop-down list.</p>
      * 
      * @param offset the horizontal offset
+     *
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
      */
     public void setDropDownHorizontalOffset(int offset) {
         mPopup.setHorizontalOffset(offset);
@@ -400,6 +397,8 @@
      * <p>Gets the horizontal offset used for the auto-complete drop-down list.</p>
      * 
      * @return the horizontal offset
+     *
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
      */
     public int getDropDownHorizontalOffset() {
         return mPopup.getHorizontalOffset();
@@ -629,7 +628,7 @@
      */
     public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
         if (mObserver == null) {
-            mObserver = new PopupDataSetObserver();
+            mObserver = new PopupDataSetObserver(this);
         } else if (mAdapter != null) {
             mAdapter.unregisterDataSetObserver(mObserver);
         }
@@ -1255,25 +1254,44 @@
         }
     }
 
-    private class PopupDataSetObserver extends DataSetObserver {
+    /**
+     * Static inner listener that keeps a WeakReference to the actual AutoCompleteTextView.
+     * <p>
+     * This way, if adapter has a longer life span than the View, we won't leak the View, instead
+     * we will just leak a small Observer with 1 field.
+     */
+    private static class PopupDataSetObserver extends DataSetObserver {
+        private final WeakReference<AutoCompleteTextView> mViewReference;
+
+        private PopupDataSetObserver(AutoCompleteTextView view) {
+            mViewReference = new WeakReference<AutoCompleteTextView>(view);
+        }
+
         @Override
         public void onChanged() {
-            if (mAdapter != null) {
+            final AutoCompleteTextView textView = mViewReference.get();
+            if (textView != null && textView.mAdapter != null) {
                 // If the popup is not showing already, showing it will cause
                 // the list of data set observers attached to the adapter to
                 // change. We can't do it from here, because we are in the middle
                 // of iterating through the list of observers.
-                post(new Runnable() {
-                    public void run() {
-                        final ListAdapter adapter = mAdapter;
-                        if (adapter != null) {
-                            // This will re-layout, thus resetting mDataChanged, so that the
-                            // listView click listener stays responsive
-                            updateDropDownForFilter(adapter.getCount());
-                        }
-                    }
-                });
+                textView.post(updateRunnable);
             }
         }
+
+        private final Runnable updateRunnable = new Runnable() {
+            @Override
+            public void run() {
+                final AutoCompleteTextView textView = mViewReference.get();
+                if (textView == null) {
+                    return;
+                }
+                final ListAdapter adapter = textView.mAdapter;
+                if (adapter == null) {
+                    return;
+                }
+                textView.updateDropDownForFilter(adapter.getCount());
+            }
+        };
     }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 29c8298..46b225d 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -147,7 +147,7 @@
         boolean isDirty;
         public TextDisplayList(String name) {
             isDirty = true;
-            displayList = RenderNode.create(name);
+            displayList = RenderNode.create(name, null);
         }
         boolean needsRecord() { return isDirty || !displayList.isValid(); }
     }
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 6a514ba..3c186e3 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.database.DataSetObserver;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -40,6 +41,7 @@
 import android.view.ViewParent;
 import android.view.animation.AccelerateDecelerateInterpolator;
 
+import com.android.internal.R;
 import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
 
 import java.util.Locale;
@@ -208,6 +210,18 @@
      */
     public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         mContext = context;
+
+        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPopupWindow,
+                defStyleAttr, defStyleRes);
+        mDropDownHorizontalOffset = a.getDimensionPixelOffset(
+                R.styleable.ListPopupWindow_dropDownHorizontalOffset, 0);
+        mDropDownVerticalOffset = a.getDimensionPixelOffset(
+                R.styleable.ListPopupWindow_dropDownVerticalOffset, 0);
+        if (mDropDownVerticalOffset != 0) {
+            mDropDownVerticalOffsetSet = true;
+        }
+        a.recycle();
+
         mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes);
         mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
         // Set the default layout direction to match the default locale one
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 602f955..56bdb9b 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -176,7 +176,7 @@
                 RemoteViewsAdapter adapter;
                 final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
                 if ((adapter = mAdapter.get()) != null) {
-                    mgr.unbindRemoteViewsService(context.getPackageName(), appWidgetId, intent);
+                    mgr.unbindRemoteViewsService(context.getOpPackageName(), appWidgetId, intent);
                 } else {
                     Slog.w(TAG, "unbind: adapter was null");
                 }
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 9914800..98d52ff 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -49,14 +49,14 @@
  *
  * <p>See the <a href="{@docRoot}guide/topics/ui/controls/spinner.html">Spinners</a> guide.</p>
  *
- * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
  * @attr ref android.R.styleable#Spinner_dropDownSelector
- * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
  * @attr ref android.R.styleable#Spinner_dropDownWidth
  * @attr ref android.R.styleable#Spinner_gravity
  * @attr ref android.R.styleable#Spinner_popupBackground
  * @attr ref android.R.styleable#Spinner_prompt
  * @attr ref android.R.styleable#Spinner_spinnerMode
+ * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
+ * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
  */
 @Widget
 public class Spinner extends AbsSpinner implements OnClickListener {
@@ -209,17 +209,6 @@
                     ViewGroup.LayoutParams.WRAP_CONTENT);
             popup.setBackgroundDrawable(a.getDrawable(
                     com.android.internal.R.styleable.Spinner_popupBackground));
-            final int verticalOffset = a.getDimensionPixelOffset(
-                    com.android.internal.R.styleable.Spinner_dropDownVerticalOffset, 0);
-            if (verticalOffset != 0) {
-                popup.setVerticalOffset(verticalOffset);
-            }
-
-            final int horizontalOffset = a.getDimensionPixelOffset(
-                    com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0);
-            if (horizontalOffset != 0) {
-                popup.setHorizontalOffset(horizontalOffset);
-            }
 
             mPopup = popup;
             mForwardingListener = new ForwardingListener(this) {
@@ -303,7 +292,7 @@
      *
      * @param pixels Vertical offset in pixels
      *
-     * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
      */
     public void setDropDownVerticalOffset(int pixels) {
         mPopup.setVerticalOffset(pixels);
@@ -315,7 +304,7 @@
      *
      * @return Vertical offset in pixels
      *
-     * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
      */
     public int getDropDownVerticalOffset() {
         return mPopup.getVerticalOffset();
@@ -327,7 +316,7 @@
      *
      * @param pixels Horizontal offset in pixels
      *
-     * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
      */
     public void setDropDownHorizontalOffset(int pixels) {
         mPopup.setHorizontalOffset(pixels);
@@ -339,7 +328,7 @@
      *
      * @return Horizontal offset in pixels
      *
-     * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
+     * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
      */
     public int getDropDownHorizontalOffset() {
         return mPopup.getHorizontalOffset();
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 818efaa..ece8aa4 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -244,6 +244,16 @@
         // Set the default context, since setPopupTheme() may be a no-op.
         mPopupContext = mContext;
         setPopupTheme(a.getResourceId(R.styleable.Toolbar_popupTheme, 0));
+
+        final Drawable navIcon = a.getDrawable(R.styleable.Toolbar_navigationIcon);
+        if (navIcon != null) {
+            setNavigationIcon(navIcon);
+            final CharSequence navDesc = a.getText(
+                    R.styleable.Toolbar_navigationContentDescription);
+            if (!TextUtils.isEmpty(navDesc)) {
+                setNavigationContentDescription(navDesc);
+            }
+        }
         a.recycle();
     }
 
@@ -669,6 +679,8 @@
      * as screen readers or tooltips.
      *
      * @return The navigation button's content description
+     *
+     * @attr ref android.R.styleable#Toolbar_navigationContentDescription
      */
     @Nullable
     public CharSequence getNavigationContentDescription() {
@@ -682,6 +694,8 @@
      *
      * @param resId Resource ID of a content description string to set, or 0 to
      *              clear the description
+     *
+     * @attr ref android.R.styleable#Toolbar_navigationContentDescription
      */
     public void setNavigationContentDescription(int resId) {
         setNavigationContentDescription(resId != 0 ? getContext().getText(resId) : null);
@@ -694,6 +708,8 @@
      *
      * @param description Content description to set, or <code>null</code> to
      *                    clear the content description
+     *
+     * @attr ref android.R.styleable#Toolbar_navigationContentDescription
      */
     public void setNavigationContentDescription(@Nullable CharSequence description) {
         if (!TextUtils.isEmpty(description)) {
@@ -715,6 +731,8 @@
      * tooltips.</p>
      *
      * @param resId Resource ID of a drawable to set
+     *
+     * @attr ref android.R.styleable#Toolbar_navigationIcon
      */
     public void setNavigationIcon(int resId) {
         setNavigationIcon(getContext().getDrawable(resId));
@@ -731,6 +749,8 @@
      * tooltips.</p>
      *
      * @param icon Drawable to set, may be null to clear the icon
+     *
+     * @attr ref android.R.styleable#Toolbar_navigationIcon
      */
     public void setNavigationIcon(@Nullable Drawable icon) {
         if (icon != null) {
@@ -751,6 +771,8 @@
      * Return the current drawable used as the navigation icon.
      *
      * @return The navigation icon drawable
+     *
+     * @attr ref android.R.styleable#Toolbar_navigationIcon
      */
     @Nullable
     public Drawable getNavigationIcon() {
@@ -1316,6 +1338,8 @@
             final View bottomChild = layoutSubtitle ? mSubtitleTextView : mTitleTextView;
             final LayoutParams toplp = (LayoutParams) topChild.getLayoutParams();
             final LayoutParams bottomlp = (LayoutParams) bottomChild.getLayoutParams();
+            final boolean titleHasWidth = layoutTitle && mTitleTextView.getMeasuredWidth() > 0
+                    || layoutSubtitle && mSubtitleTextView.getMeasuredWidth() > 0;
 
             switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
                 case Gravity.TOP:
@@ -1343,7 +1367,7 @@
                     break;
             }
             if (isRtl) {
-                final int rd = mTitleMarginStart - collapsingMargins[1];
+                final int rd = (titleHasWidth ? mTitleMarginStart : 0) - collapsingMargins[1];
                 right -= Math.max(0, rd);
                 collapsingMargins[1] = Math.max(0, -rd);
                 int titleRight = right;
@@ -1366,9 +1390,11 @@
                     subtitleRight = subtitleRight - mTitleMarginEnd;
                     titleTop = subtitleBottom + lp.bottomMargin;
                 }
-                right = Math.min(titleRight, subtitleRight);
+                if (titleHasWidth) {
+                    right = Math.min(titleRight, subtitleRight);
+                }
             } else {
-                final int ld = mTitleMarginStart - collapsingMargins[0];
+                final int ld = (titleHasWidth ? mTitleMarginStart : 0) - collapsingMargins[0];
                 left += Math.max(0, ld);
                 collapsingMargins[0] = Math.max(0, -ld);
                 int titleLeft = left;
@@ -1391,7 +1417,9 @@
                     subtitleLeft = subtitleRight + mTitleMarginEnd;
                     titleTop = subtitleBottom + lp.bottomMargin;
                 }
-                left = Math.max(titleLeft, subtitleLeft);
+                if (titleHasWidth) {
+                    left = Math.max(titleLeft, subtitleLeft);
+                }
             }
         }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index ee406bd..eae4427 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -993,6 +993,6 @@
         } catch (RemoteException e) {
             Log.w(TAG, "RemoteException:", e);
         }
-        return null;
+        return new BatteryStatsImpl();
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 299b0e6..69cdbff 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2487,6 +2487,16 @@
         addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
     }
 
+    public void noteCurrentTimeChangedLocked() {
+        final long currentTime = System.currentTimeMillis();
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
+        if (isStartClockTimeValid()) {
+            mStartClockTime = currentTime;
+        }
+    }
+
     public void noteProcessStartLocked(String name, int uid) {
         uid = mapUid(uid);
         if (isOnBattery()) {
@@ -4060,7 +4070,20 @@
         }
     }
 
+    boolean isStartClockTimeValid() {
+        return mStartClockTime > 365*24*60*60*1000L;
+    }
+
     @Override public long getStartClockTime() {
+        if (!isStartClockTimeValid()) {
+            // If the last clock time we got was very small, then we hadn't had a real
+            // time yet, so try to get it again.
+            mStartClockTime = System.currentTimeMillis();
+            if (isStartClockTimeValid()) {
+                recordCurrentTimeChangeLocked(mStartClockTime, SystemClock.elapsedRealtime(),
+                        SystemClock.uptimeMillis());
+            }
+        }
         return mStartClockTime;
     }
 
@@ -6799,6 +6822,16 @@
         }
     }
 
+    private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs,
+            final long uptimeMs) {
+        if (mRecordingHistory) {
+            mHistoryCur.currentTime = currentTime;
+            addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
+                    mHistoryCur);
+            mHistoryCur.currentTime = 0;
+        }
+    }
+
     // This should probably be exposed in the API, though it's not critical
     private static final int BATTERY_PLUGGED_NONE = 0;
 
@@ -8004,6 +8037,10 @@
     public void writeSummaryToParcel(Parcel out, boolean inclHistory) {
         pullPendingStateUpdatesLocked();
 
+        // Pull the clock time.  This may update the time and make a new history entry
+        // if we had originally pulled a time before the RTC was set.
+        long startClockTime = getStartClockTime();
+
         final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
         final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
 
@@ -8014,7 +8051,7 @@
         out.writeInt(mStartCount);
         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
-        out.writeLong(mStartClockTime);
+        out.writeLong(startClockTime);
         out.writeString(mStartPlatformVersion);
         out.writeString(mEndPlatformVersion);
         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
@@ -8453,6 +8490,10 @@
         // Need to update with current kernel wake lock counts.
         pullPendingStateUpdatesLocked();
 
+        // Pull the clock time.  This may update the time and make a new history entry
+        // if we had originally pulled a time before the RTC was set.
+        long startClockTime = getStartClockTime();
+
         final long uSecUptime = SystemClock.uptimeMillis() * 1000;
         final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
@@ -8463,7 +8504,7 @@
         writeHistory(out, true, false);
 
         out.writeInt(mStartCount);
-        out.writeLong(mStartClockTime);
+        out.writeLong(startClockTime);
         out.writeString(mStartPlatformVersion);
         out.writeString(mEndPlatformVersion);
         out.writeLong(mUptime);
@@ -8588,6 +8629,10 @@
     public void prepareForDumpLocked() {
         // Need to retrieve current kernel wake lock stats before printing.
         pullPendingStateUpdatesLocked();
+
+        // Pull the clock time.  This may update the time and make a new history entry
+        // if we had originally pulled a time before the RTC was set.
+        getStartClockTime();
     }
 
     public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 2967938..ba236f39 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -191,6 +191,20 @@
     public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
         if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode);
 
+        // It is possible that any other bit is used as a valid flag in a future release.
+        // We should reject the entire request in such a case.
+        final int KNOWN_FLAGS_MASK = InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE |
+                InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR;
+        final int unknownFlags = cursorUpdateMode & ~KNOWN_FLAGS_MASK;
+        if (unknownFlags != 0) {
+            if (DEBUG) {
+                Log.d(TAG, "Rejecting requestUpdateCursorAnchorInfo due to unknown flags." +
+                        " cursorUpdateMode=" + cursorUpdateMode +
+                        " unknownFlags=" + unknownFlags);
+            }
+            return false;
+        }
+
         if (mIMM == null) {
             // In this case, TYPE_CURSOR_ANCHOR_INFO is not handled.
             // TODO: Return some notification code rather than false to indicate method that
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a8b8bef..62d8036 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -879,9 +879,17 @@
         parseRuntimeOption("dalvik.vm.profile.max-stack-depth",
                            profileMaxStackDepth,
                            "-Xprofile-max-stack-depth:");
-    }
 
-    parseRuntimeOption("ro.dalvik.vm.native.bridge", nativeBridgeLibrary, "-XX:NativeBridge=");
+        // Native bridge library. "0" means that native bridge is disabled.
+        property_get("ro.dalvik.vm.native.bridge", propBuf, "");
+        if (propBuf[0] == '\0') {
+            ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
+        } else if (strcmp(propBuf, "0") != 0) {
+            snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
+                     "-XX:NativeBridge=%s", propBuf);
+            addOption(nativeBridgeLibrary);
+        }
+    }
 
     initArgs.version = JNI_VERSION_1_4;
     initArgs.options = mOptions.editArray();
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 1d465b3..bfb30b7 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -62,10 +62,26 @@
         ALOGE("addFont failed to create font %s", str.c_str());
         return false;
     }
-    FontFamily* fontFamily = (FontFamily*)familyPtr;
+    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
     return addSkTypeface(fontFamily, face);
 }
 
+static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr,
+        jstring path, jint weight, jboolean isItalic) {
+    NPE_CHECK_RETURN_ZERO(env, path);
+    ScopedUtfChars str(env, path);
+    SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
+    if (face == NULL) {
+        ALOGE("addFont failed to create font %s", str.c_str());
+        return false;
+    }
+    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
+    MinikinFont* minikinFont = new MinikinFontSkia(face);
+    fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic));
+    minikinFont->Unref();
+    return true;
+}
+
 static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
         jobject jassetMgr, jstring jpath) {
     NPE_CHECK_RETURN_ZERO(env, jassetMgr);
@@ -92,17 +108,18 @@
         ALOGE("addFontFromAsset failed to create font %s", str.c_str());
         return false;
     }
-    FontFamily* fontFamily = (FontFamily*)familyPtr;
+    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
     return addSkTypeface(fontFamily, face);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 static JNINativeMethod gFontFamilyMethods[] = {
-    { "nCreateFamily",            "(Ljava/lang/String;I)J", (void*)FontFamily_create },
-    { "nUnrefFamily",             "(J)V", (void*)FontFamily_unref },
-    { "nAddFont",                 "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
-    { "nAddFontFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
+    { "nCreateFamily",         "(Ljava/lang/String;I)J", (void*)FontFamily_create },
+    { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
+    { "nAddFont",              "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
+    { "nAddFontWeightStyle",   "(JLjava/lang/String;IZ)Z", (void*)FontFamily_addFontWeightStyle },
+    { "nAddFontFromAsset",     "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
                                            (void*)FontFamily_addFontFromAsset },
 };
 
diff --git a/core/jni/android/graphics/MinikinSkia.cpp b/core/jni/android/graphics/MinikinSkia.cpp
index ae29014..4649b07 100644
--- a/core/jni/android/graphics/MinikinSkia.cpp
+++ b/core/jni/android/graphics/MinikinSkia.cpp
@@ -39,7 +39,7 @@
     uint16_t glyph16;
     paint.textToGlyphs(&codepoint, sizeof(codepoint), &glyph16);
     *glyph  = glyph16;
-    return !!glyph;
+    return !!glyph16;
 }
 
 static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index cf4e838..2029658 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -41,6 +41,12 @@
     return reinterpret_cast<jlong>(face);
 }
 
+static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
+    TypefaceImpl* family = reinterpret_cast<TypefaceImpl*>(familyHandle);
+    TypefaceImpl* face = TypefaceImpl_createWeightAlias(family, weight);
+    return reinterpret_cast<jlong>(face);
+}
+
 static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
     TypefaceImpl* face = reinterpret_cast<TypefaceImpl*>(faceHandle);
     TypefaceImpl_unref(face);
@@ -65,6 +71,7 @@
 
 static JNINativeMethod gTypefaceMethods[] = {
     { "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
+    { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
     { "nativeUnref",              "(J)V",  (void*)Typeface_unref },
     { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
     { "nativeCreateFromArray",    "([J)J",
diff --git a/core/jni/android/graphics/TypefaceImpl.cpp b/core/jni/android/graphics/TypefaceImpl.cpp
index 9ce6de1..7afbeb2 100644
--- a/core/jni/android/graphics/TypefaceImpl.cpp
+++ b/core/jni/android/graphics/TypefaceImpl.cpp
@@ -39,14 +39,17 @@
 
 namespace android {
 
-// Any weight greater than or equal to this is considered "bold" for
-// legacy API.
-static const int kBoldThreshold = 6;
-
-static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) {
-    int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4;
-    bool italic = (skiaStyle & SkTypeface::kItalic) != 0;
-    return FontStyle(weight, italic);
+// Resolve the 1..9 weight based on base weight and bold flag
+static void resolveStyle(TypefaceImpl* typeface) {
+    int weight = typeface->fBaseWeight / 100;
+    if (typeface->fSkiaStyle & SkTypeface::kBold) {
+        weight += 3;
+    }
+    if (weight > 9) {
+        weight = 9;
+    }
+    bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
+    typeface->fStyle = FontStyle(weight, italic);
 }
 
 TypefaceImpl* gDefaultTypeface = NULL;
@@ -90,7 +93,9 @@
         // default so we can make progress before that happens.
         gDefaultTypeface = new TypefaceImpl;
         gDefaultTypeface->fFontCollection = makeFontCollection();
-        gDefaultTypeface->fStyle = FontStyle();
+        gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
+        gDefaultTypeface->fBaseWeight = 400;
+        resolveStyle(gDefaultTypeface);
     }
 }
 
@@ -109,25 +114,23 @@
     if (result != 0) {
         result->fFontCollection = resolvedFace->fFontCollection;
         result->fFontCollection->Ref();
-        result->fStyle = styleFromSkiaStyle(style);
+        result->fSkiaStyle = style;
+        result->fBaseWeight = resolvedFace->fBaseWeight;
+        resolveStyle(result);
     }
     return result;
 }
 
-static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
-    if (typeface == NULL) {
-        return NULL;
-    }
-    MinikinFont* minikinFont = new MinikinFontSkia(typeface);
-    std::vector<FontFamily *> typefaces;
-    FontFamily* family = new FontFamily();
-    family->addFont(minikinFont);
-    minikinFont->Unref();
-    typefaces.push_back(family);
+TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
+    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
     TypefaceImpl* result = new TypefaceImpl;
-    result->fFontCollection = new FontCollection(typefaces);
-    family->Unref();
-    result->fStyle = FontStyle();  // TODO: improve
+    if (result != 0) {
+        result->fFontCollection = resolvedFace->fFontCollection;
+        result->fFontCollection->Ref();
+        result->fSkiaStyle = resolvedFace->fSkiaStyle;
+        result->fBaseWeight = weight;
+        resolveStyle(result);
+    }
     return result;
 }
 
@@ -141,7 +144,7 @@
     result->fFontCollection = new FontCollection(familyVec);
     if (size == 0) {
         ALOGW("createFromFamilies creating empty collection");
-        result->fStyle = FontStyle();
+        result->fSkiaStyle = SkTypeface::kNormal;
     } else {
         const FontStyle defaultStyle;
         FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
@@ -150,11 +153,13 @@
             SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
             // TODO: probably better to query more precise style from family, will be important
             // when we open up API to access 100..900 weights
-            result->fStyle = styleFromSkiaStyle(skTypeface->style());
+            result->fSkiaStyle = skTypeface->style();
         } else {
-            result->fStyle = defaultStyle;
+            result->fSkiaStyle = SkTypeface::kNormal;
         }
     }
+    result->fBaseWeight = 400;
+    resolveStyle(result);
     return result;
 }
 
@@ -166,12 +171,7 @@
 }
 
 int TypefaceImpl_getStyle(TypefaceImpl* face) {
-    FontStyle style = face->fStyle;
-    int result = style.getItalic() ? SkTypeface::kItalic : 0;
-    if (style.getWeight() >= kBoldThreshold) {
-        result |= SkTypeface::kBold;
-    }
-    return result;
+    return face->fSkiaStyle;
 }
 
 void TypefaceImpl_setDefault(TypefaceImpl* face) {
diff --git a/core/jni/android/graphics/TypefaceImpl.h b/core/jni/android/graphics/TypefaceImpl.h
index 12b3403..d129f621 100644
--- a/core/jni/android/graphics/TypefaceImpl.h
+++ b/core/jni/android/graphics/TypefaceImpl.h
@@ -28,6 +28,13 @@
 
 struct TypefaceImpl {
     FontCollection *fFontCollection;
+
+    // style used for constructing and querying Typeface objects
+    SkTypeface::Style fSkiaStyle;
+    // base weight in CSS-style units, 100..900
+    int fBaseWeight;
+
+    // resolved style actually used for rendering
     FontStyle fStyle;
 };
 
@@ -41,6 +48,8 @@
 
 TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style);
 
+TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int baseweight);
+
 // When we remove the USE_MINIKIN ifdef, probably a good idea to move the casting
 // (from jlong to FontFamily*) to the caller in Typeface.cpp.
 TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size);
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 1e9d722..1296831 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -455,6 +455,12 @@
     renderNode->addAnimator(animator);
 }
 
+static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
+        jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->animators().endAllAnimators();
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -534,6 +540,7 @@
     { "nGetPivotY",                "(J)F",  (void*) android_view_RenderNode_getPivotY },
 
     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
+    { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
 #endif
 };
 
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 767534f..85c2a09 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -51,28 +51,36 @@
     // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!"
     // then you end up with basically a PhantomReference, which is totally not
     // what we want.
-    AnimationListenerBridge(JNIEnv* env, jobject weakThis) {
-        mWeakThis = env->NewGlobalRef(weakThis);
+    AnimationListenerBridge(JNIEnv* env, jobject finishListener) {
+        mFinishListener = env->NewGlobalRef(finishListener);
         env->GetJavaVM(&mJvm);
     }
 
     virtual ~AnimationListenerBridge() {
-        JNIEnv* env = getEnv(mJvm);
-        env->DeleteGlobalRef(mWeakThis);
-        mWeakThis = NULL;
+        if (mFinishListener) {
+            onAnimationFinished(NULL);
+        }
     }
 
     virtual void onAnimationFinished(BaseRenderNodeAnimator*) {
+        LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?");
         JNIEnv* env = getEnv(mJvm);
         env->CallStaticVoidMethod(
                 gRenderNodeAnimatorClassInfo.clazz,
                 gRenderNodeAnimatorClassInfo.callOnFinished,
-                mWeakThis);
+                mFinishListener);
+        releaseJavaObject();
     }
 
 private:
+    void releaseJavaObject() {
+        JNIEnv* env = getEnv(mJvm);
+        env->DeleteGlobalRef(mFinishListener);
+        mFinishListener = NULL;
+    }
+
     JavaVM* mJvm;
-    jobject mWeakThis;
+    jobject mFinishListener;
 };
 
 static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) {
@@ -88,38 +96,33 @@
     return static_cast<CanvasPropertyPaintAnimator::PaintField>(field);
 }
 
-static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+static jlong createAnimator(JNIEnv* env, jobject clazz,
         jint propertyRaw, jfloat finalValue) {
     RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
-
     BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue);
-    animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
-        jobject weakThis, jlong canvasPropertyPtr, jfloat finalValue) {
+        jlong canvasPropertyPtr, jfloat finalValue) {
     CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
     BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue);
-    animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
 static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
-        jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
+        jlong canvasPropertyPtr, jint paintFieldRaw,
         jfloat finalValue) {
     CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
     CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
     BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator(
             canvasProperty, paintField, finalValue);
-    animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
-static jlong createRevealAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+static jlong createRevealAnimator(JNIEnv* env, jobject clazz,
         jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) {
     BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius);
-    animator->setListener(new AnimationListenerBridge(env, weakThis));
     return reinterpret_cast<jlong>( animator );
 }
 
@@ -156,8 +159,11 @@
     animator->setInterpolator(interpolator);
 }
 
-static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) {
+static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
     BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
+    if (finishListener) {
+        animator->setListener(new AnimationListenerBridge(env, finishListener));
+    }
     animator->start();
 }
 
@@ -176,17 +182,16 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
-    { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator },
-    { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator },
-    { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator },
-    { "nCreateRevealAnimator", "(Ljava/lang/ref/WeakReference;IIFF)J", (void*) createRevealAnimator },
+    { "nCreateAnimator", "(IF)J", (void*) createAnimator },
+    { "nCreateCanvasPropertyFloatAnimator", "(JF)J", (void*) createCanvasPropertyFloatAnimator },
+    { "nCreateCanvasPropertyPaintAnimator", "(JIF)J", (void*) createCanvasPropertyPaintAnimator },
+    { "nCreateRevealAnimator", "(IIFF)J", (void*) createRevealAnimator },
     { "nSetStartValue", "(JF)V", (void*) setStartValue },
     { "nSetDuration", "(JJ)V", (void*) setDuration },
     { "nGetDuration", "(J)J", (void*) getDuration },
     { "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
-    { "nGetStartDelay", "(J)J", (void*) getStartDelay },
     { "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
-    { "nStart", "(J)V", (void*) start },
+    { "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start },
     { "nEnd", "(J)V", (void*) end },
 #endif
 };
@@ -204,7 +209,7 @@
     gRenderNodeAnimatorClassInfo.clazz = jclass(env->NewGlobalRef(gRenderNodeAnimatorClassInfo.clazz));
 
     GET_STATIC_METHOD_ID(gRenderNodeAnimatorClassInfo.callOnFinished, gRenderNodeAnimatorClassInfo.clazz,
-            "callOnFinished", "(Ljava/lang/ref/WeakReference;)V");
+            "callOnFinished", "(Landroid/view/RenderNodeAnimator;)V");
 
     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 4e3419a..99babac 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -33,6 +33,8 @@
 #include "android_view_GraphicBuffer.h"
 
 #include <Animator.h>
+#include <AnimationContext.h>
+#include <IContextFactory.h>
 #include <RenderNode.h>
 #include <renderthread/CanvasContext.h>
 #include <renderthread/RenderProxy.h>
@@ -103,7 +105,7 @@
     std::string mMessage;
 };
 
-class RootRenderNode : public RenderNode, AnimationHook, ErrorHandler {
+class RootRenderNode : public RenderNode, ErrorHandler {
 public:
     RootRenderNode(JNIEnv* env) : RenderNode() {
         mLooper = Looper::getForThread();
@@ -114,34 +116,84 @@
 
     virtual ~RootRenderNode() {}
 
-    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
-        OnFinishedEvent event(animator, listener);
-        mOnFinishedEvents.push_back(event);
-    }
-
     virtual void onError(const std::string& message) {
         mLooper->sendMessage(new RenderingException(mVm, message), 0);
     }
 
     virtual void prepareTree(TreeInfo& info) {
-        info.animationHook = this;
         info.errorHandler = this;
         RenderNode::prepareTree(info);
-        info.animationHook = NULL;
         info.errorHandler = NULL;
+    }
 
-        // post all the finished stuff
-        if (mOnFinishedEvents.size()) {
-            sp<InvokeAnimationListeners> message
-                    = new InvokeAnimationListeners(mOnFinishedEvents);
-            mLooper->sendMessage(message, 0);
+    void sendMessage(const sp<MessageHandler>& handler) {
+        mLooper->sendMessage(handler, 0);
+    }
+
+    void attachAnimatingNode(RenderNode* animatingNode) {
+        mPendingAnimatingRenderNodes.push_back(animatingNode);
+    }
+
+    void doAttachAnimatingNodes(AnimationContext* context) {
+        for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
+            RenderNode* node = mPendingAnimatingRenderNodes[i].get();
+            context->addAnimatingRenderNode(*node);
         }
+        mPendingAnimatingRenderNodes.clear();
     }
 
 private:
     sp<Looper> mLooper;
-    std::vector<OnFinishedEvent> mOnFinishedEvents;
     JavaVM* mVm;
+    std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
+};
+
+class AnimationContextBridge : public AnimationContext {
+public:
+    AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
+            : AnimationContext(clock), mRootNode(rootNode) {
+    }
+
+    virtual ~AnimationContextBridge() {}
+
+    // Marks the start of a frame, which will update the frame time and move all
+    // next frame animations into the current frame
+    virtual void startFrame() {
+        mRootNode->doAttachAnimatingNodes(this);
+        AnimationContext::startFrame();
+    }
+
+    // Runs any animations still left in mCurrentFrameAnimations
+    virtual void runRemainingAnimations(TreeInfo& info) {
+        AnimationContext::runRemainingAnimations(info);
+        // post all the finished stuff
+        if (mOnFinishedEvents.size()) {
+            sp<InvokeAnimationListeners> message
+                    = new InvokeAnimationListeners(mOnFinishedEvents);
+            mRootNode->sendMessage(message);
+        }
+    }
+
+    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
+        OnFinishedEvent event(animator, listener);
+        mOnFinishedEvents.push_back(event);
+    }
+
+private:
+    sp<RootRenderNode> mRootNode;
+    std::vector<OnFinishedEvent> mOnFinishedEvents;
+};
+
+class ContextFactoryImpl : public IContextFactory {
+public:
+    ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
+
+    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
+        return new AnimationContextBridge(clock, mRootNode);
+    }
+
+private:
+    RootRenderNode* mRootNode;
 };
 
 static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
@@ -168,8 +220,9 @@
 
 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
         jboolean translucent, jlong rootRenderNodePtr) {
-    RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr);
-    return (jlong) new RenderProxy(translucent, rootRenderNode);
+    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
+    ContextFactoryImpl factory(rootRenderNode);
+    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
 }
 
 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
@@ -244,6 +297,13 @@
     proxy->destroyCanvasAndSurface();
 }
 
+static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
+        jlong rootNodePtr, jlong animatingNodePtr) {
+    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
+    RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
+    rootRenderNode->attachAnimatingNode(animatingNode);
+}
+
 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
         jlong functorPtr, jboolean waitForCompletion) {
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
@@ -371,6 +431,7 @@
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
     { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
+    { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
diff --git a/core/res/res/drawable/btn_borderless_material.xml b/core/res/res/drawable/btn_borderless_material.xml
index 016f0ff..08e1060 100644
--- a/core/res/res/drawable/btn_borderless_material.xml
+++ b/core/res/res/drawable/btn_borderless_material.xml
@@ -14,10 +14,8 @@
      limitations under the License.
 -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:inset="@dimen/control_inset_material">
-    <ripple android:color="?attr/colorControlHighlight">
-        <item android:id="@id/mask"
-              android:drawable="@drawable/btn_default_mtrl_shape" />
-    </ripple>
-</inset>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?attr/colorControlHighlight">
+    <item android:id="@id/mask"
+          android:drawable="@drawable/btn_default_mtrl_shape" />
+</ripple>
diff --git a/core/res/res/drawable/btn_default_material.xml b/core/res/res/drawable/btn_default_material.xml
index d00a348..ed2b5aa 100644
--- a/core/res/res/drawable/btn_default_material.xml
+++ b/core/res/res/drawable/btn_default_material.xml
@@ -14,9 +14,7 @@
      limitations under the License.
 -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:inset="@dimen/control_inset_material">
-    <ripple android:color="?attr/colorControlHighlight">
-        <item android:drawable="@drawable/btn_default_mtrl_shape" />
-    </ripple>
-</inset>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?attr/colorControlHighlight">
+    <item android:drawable="@drawable/btn_default_mtrl_shape" />
+</ripple>
diff --git a/core/res/res/drawable/btn_default_mtrl_shape.xml b/core/res/res/drawable/btn_default_mtrl_shape.xml
index 9235c76..6d0f7f8 100644
--- a/core/res/res/drawable/btn_default_mtrl_shape.xml
+++ b/core/res/res/drawable/btn_default_mtrl_shape.xml
@@ -15,12 +15,18 @@
 -->
 
 <!-- Used as the canonical button shape. -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-    <corners android:radius="@dimen/control_corner_material" />
-    <solid android:color="?attr/colorButtonNormal" />
-    <padding android:top="@dimen/control_padding_material"
-             android:bottom="@dimen/control_padding_material"
-             android:left="@dimen/control_padding_material"
-             android:right="@dimen/control_padding_material" />
-</shape>
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:insetLeft="@dimen/button_inset_horizontal_material"
+       android:insetTop="@dimen/button_inset_vertical_material"
+       android:insetRight="@dimen/button_inset_horizontal_material"
+       android:insetBottom="@dimen/button_inset_vertical_material">
+    <shape android:shape="rectangle">
+        <corners android:radius="@dimen/control_corner_material" />
+        <solid android:color="?attr/colorButtonNormal" />
+        <padding android:left="@dimen/button_padding_horizontal_material"
+                 android:top="@dimen/button_padding_vertical_material"
+                 android:right="@dimen/button_padding_horizontal_material"
+                 android:bottom="@dimen/button_padding_vertical_material" />
+    </shape>
+</inset>
diff --git a/core/res/res/drawable/btn_toggle_material.xml b/core/res/res/drawable/btn_toggle_material.xml
index 9726782..f91d4cc 100644
--- a/core/res/res/drawable/btn_toggle_material.xml
+++ b/core/res/res/drawable/btn_toggle_material.xml
@@ -15,7 +15,10 @@
 -->
 
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-       android:inset="@dimen/control_inset_material">
+       android:insetLeft="@dimen/button_inset_horizontal_material"
+       android:insetTop="@dimen/button_inset_vertical_material"
+       android:insetRight="@dimen/button_inset_horizontal_material"
+       android:insetBottom="@dimen/button_inset_vertical_material">
     <layer-list android:paddingMode="stack">
         <item>
             <ripple android:color="?attr/colorControlHighlight">
@@ -25,10 +28,10 @@
                         <corners android:topLeftRadius="@dimen/control_corner_material"
                                  android:topRightRadius="@dimen/control_corner_material"/>
                         <solid android:color="?attr/colorButtonNormal" />
-                        <padding android:top="@dimen/control_padding_material"
-                                 android:bottom="@dimen/control_padding_material"
-                                 android:left="@dimen/control_padding_material"
-                                 android:right="@dimen/control_padding_material" />
+                        <padding android:left="@dimen/button_padding_horizontal_material"
+                                 android:top="@dimen/button_padding_vertical_material"
+                                 android:right="@dimen/button_padding_horizontal_material"
+                                 android:bottom="@dimen/button_padding_vertical_material" />
                     </shape>
                 </item>
             </ripple>
diff --git a/core/res/res/drawable/progress_horizontal_material.xml b/core/res/res/drawable/progress_horizontal_material.xml
index d7440a9..7a1079c 100644
--- a/core/res/res/drawable/progress_horizontal_material.xml
+++ b/core/res/res/drawable/progress_horizontal_material.xml
@@ -17,7 +17,8 @@
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@id/background">
         <nine-patch android:src="@drawable/progress_mtrl_alpha"
-            android:tint="?attr/colorControlNormal" />
+            android:tint="?attr/colorControlNormal"
+            android:alpha="0.5" />
     </item>
     <item android:id="@id/secondaryProgress">
         <scale android:scaleWidth="100%">
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index f264b7b..ef916ed1 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -45,7 +45,7 @@
             android:gravity="top"
             >
             <TextView android:id="@+id/big_text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
@@ -53,8 +53,8 @@
                 android:visibility="gone"
                 />
             <ImageView android:id="@+id/profile_badge_large_template"
-                android:layout_width="20dp"
-                android:layout_height="20dp"
+                android:layout_width="@dimen/notification_badge_size"
+                android:layout_height="@dimen/notification_badge_size"
                 android:layout_weight="0"
                 android:layout_marginStart="4dp"
                 android:scaleType="fitCenter"
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index f8e1986..3c44141 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -49,7 +49,7 @@
                 android:orientation="horizontal"
                 >
                 <TextView android:id="@+id/title"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
+                    android:textAppearance="@style/TextAppearance.Material.Notification.Title"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:singleLine="true"
@@ -73,7 +73,7 @@
                     />
             </LinearLayout>
             <TextView android:id="@+id/text2"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
+                android:textAppearance="@style/TextAppearance.Material.Notification.Line2"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="-2dp"
@@ -86,7 +86,7 @@
                 android:visibility="gone"
                 />
             <TextView android:id="@+id/big_text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="8dp"
@@ -104,7 +104,7 @@
                 android:gravity="center_vertical"
                 >
                 <TextView android:id="@+id/text"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+                    android:textAppearance="@style/TextAppearance.Material.Notification"
                     android:layout_width="0dp"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
@@ -114,7 +114,7 @@
                     android:fadingEdge="horizontal"
                     />
                 <TextView android:id="@+id/info"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
+                    android:textAppearance="@style/TextAppearance.Material.Notification.Info"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_gravity="center"
@@ -146,7 +146,7 @@
                 android:layout_height="6dp"
                 android:layout_gravity="top"
                 android:visibility="gone"
-                style="@style/Widget.StatusBar.Material.ProgressBar.Media"
+                style="@style/Widget.Material.Notification.ProgressBar.Media"
                 />
         </FrameLayout>
     </LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index d9120f6..3415814 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -39,14 +39,15 @@
         <include layout="@layout/notification_template_part_line2" />
         <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_height="0dp"
             android:layout_marginEnd="8dp"
             android:layout_marginBottom="10dp"
             android:orientation="horizontal"
             android:gravity="top"
+            android:layout_weight="1"
             >
             <TextView android:id="@+id/big_text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
@@ -54,8 +55,8 @@
                 android:visibility="gone"
                 />
             <ImageView android:id="@+id/profile_badge_large_template"
-                android:layout_width="20dp"
-                android:layout_height="20dp"
+                android:layout_width="@dimen/notification_badge_size"
+                android:layout_height="@dimen/notification_badge_size"
                 android:layout_weight="0"
                 android:layout_marginStart="4dp"
                 android:scaleType="fitCenter"
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 38b3ae2..2382d18 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -37,95 +37,27 @@
         >
         <include layout="@layout/notification_template_part_line1" />
         <include layout="@layout/notification_template_part_line2" />
+
+        <!-- We can't have another vertical linear layout here with weight != 0 so this forces us to
+             put the badge on the first line. -->
         <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_height="0dp"
             android:orientation="horizontal"
-            android:gravity="top"
             >
-            <LinearLayout
+            <TextView android:id="@+id/inbox_text0"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
                 android:layout_width="0dp"
-                android:layout_weight="1"
                 android:layout_height="wrap_content"
-                android:orientation="vertical"
-                >
-                <TextView android:id="@+id/inbox_text0"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_text1"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_text2"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_text3"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_text4"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_text5"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_text6"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    />
-                <TextView android:id="@+id/inbox_more"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:visibility="gone"
-                    android:layout_weight="1"
-                    android:text="@android:string/ellipsis"
-                    />
-            </LinearLayout>
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
             <ImageView android:id="@+id/profile_badge_large_template"
-                android:layout_width="20dp"
-                android:layout_height="20dp"
+                android:layout_width="@dimen/notification_badge_size"
+                android:layout_height="@dimen/notification_badge_size"
                 android:layout_weight="0"
                 android:layout_marginStart="4dp"
                 android:layout_marginEnd="8dp"
@@ -133,6 +65,77 @@
                 android:visibility="gone"
                 />
         </LinearLayout>
+        <TextView android:id="@+id/inbox_text1"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text2"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text3"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text4"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text5"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text6"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_more"
+            android:textAppearance="@style/TextAppearance.Material.Notification"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginEnd="8dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            android:text="@android:string/ellipsis"
+            />
         <FrameLayout
             android:id="@+id/inbox_end_pad"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index c2fc006..db24c1f 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -50,7 +50,7 @@
             android:orientation="horizontal"
             >
             <TextView android:id="@+id/title"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
+                android:textAppearance="@style/TextAppearance.Material.Notification.Title"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:singleLine="true"
@@ -74,7 +74,7 @@
                 />
         </LinearLayout>
         <TextView android:id="@+id/text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
+            android:textAppearance="@style/TextAppearance.Material.Notification.Line2"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="-2dp"
@@ -91,7 +91,7 @@
             android:layout_height="12dp"
             android:layout_marginStart="8dp"
             android:visibility="gone"
-            style="@style/Widget.StatusBar.Material.ProgressBar"
+            style="@style/Widget.Material.Notification.ProgressBar"
             />
         <LinearLayout
             android:id="@+id/line3"
@@ -102,7 +102,7 @@
             android:layout_marginStart="8dp"
             >
             <TextView android:id="@+id/text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
@@ -112,7 +112,7 @@
                 android:fadingEdge="horizontal"
                 />
             <TextView android:id="@+id/info"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
+                android:textAppearance="@style/TextAppearance.Material.Notification.Info"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
diff --git a/core/res/res/layout/notification_template_part_chronometer.xml b/core/res/res/layout/notification_template_part_chronometer.xml
index 87dfe1f..1f0430e 100644
--- a/core/res/res/layout/notification_template_part_chronometer.xml
+++ b/core/res/res/layout/notification_template_part_chronometer.xml
@@ -15,7 +15,7 @@
 -->
 
 <Chronometer android:id="@+id/chronometer" xmlns:android="http://schemas.android.com/apk/res/android"
-    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Time"
+    android:textAppearance="@style/TextAppearance.Material.Notification.Time"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
diff --git a/core/res/res/layout/notification_template_part_line1.xml b/core/res/res/layout/notification_template_part_line1.xml
index c6ea6bf..7de4089 100644
--- a/core/res/res/layout/notification_template_part_line1.xml
+++ b/core/res/res/layout/notification_template_part_line1.xml
@@ -23,7 +23,7 @@
     android:orientation="horizontal"
     >
     <TextView android:id="@+id/title"
-        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
+        android:textAppearance="@style/TextAppearance.Material.Notification.Title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:singleLine="true"
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index 1f95150..7e99c5e 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -20,14 +20,12 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginEnd="8dp"
-        android:visibility="gone"
-        android:layout_weight="0"
         android:orientation="horizontal"
         android:gravity="center_vertical"
         >
         <TextView
             android:id="@+id/text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
+            android:textAppearance="@style/TextAppearance.Material.Notification.Line2"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_marginTop="-1dp"
@@ -39,8 +37,8 @@
             android:layout_weight="1"
         />
         <ImageView android:id="@+id/profile_badge_line2"
-            android:layout_width="20dp"
-            android:layout_height="20dp"
+            android:layout_width="@dimen/notification_badge_size"
+            android:layout_height="@dimen/notification_badge_size"
             android:layout_weight="0"
             android:layout_marginStart="4dp"
             android:scaleType="fitCenter"
diff --git a/core/res/res/layout/notification_template_part_line3.xml b/core/res/res/layout/notification_template_part_line3.xml
index 06de2a5..6c043a0 100644
--- a/core/res/res/layout/notification_template_part_line3.xml
+++ b/core/res/res/layout/notification_template_part_line3.xml
@@ -24,7 +24,7 @@
     android:gravity="center_vertical"
     >
     <TextView android:id="@+id/text"
-        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+        android:textAppearance="@style/TextAppearance.Material.Notification"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_weight="1"
@@ -34,7 +34,7 @@
         android:fadingEdge="horizontal"
         />
     <TextView android:id="@+id/info"
-        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
+        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
@@ -44,8 +44,8 @@
         android:paddingStart="8dp"
         />
     <ImageView android:id="@+id/profile_badge_line3"
-        android:layout_width="20dp"
-        android:layout_height="20dp"
+        android:layout_width="@dimen/notification_badge_size"
+        android:layout_height="@dimen/notification_badge_size"
         android:layout_gravity="center"
         android:layout_weight="0"
         android:layout_marginStart="4dp"
diff --git a/core/res/res/layout/notification_template_part_time.xml b/core/res/res/layout/notification_template_part_time.xml
index 5982c48..37c7ebe 100644
--- a/core/res/res/layout/notification_template_part_time.xml
+++ b/core/res/res/layout/notification_template_part_time.xml
@@ -15,7 +15,7 @@
 -->
 
 <DateTimeView android:id="@+id/time" xmlns:android="http://schemas.android.com/apk/res/android"
-    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Time"
+    android:textAppearance="@style/TextAppearance.Material.Notification.Time"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
diff --git a/core/res/res/values-television/dimens.xml b/core/res/res/values-television/dimens.xml
index 8266642..69c3da5 100644
--- a/core/res/res/values-television/dimens.xml
+++ b/core/res/res/values-television/dimens.xml
@@ -16,8 +16,8 @@
 <resources>
 
      <!-- Lighting and shadow properties -->
-     <dimen name="light_y">-300dp</dimen>
-     <item type="dimen" format="float" name="ambient_shadow_alpha">0.4</item>
-     <item type="dimen" format="float" name="spot_shadow_alpha">0.4</item>
+     <dimen name="light_y">-400dp</dimen>
+     <item type="dimen" format="float" name="ambient_shadow_alpha">0.06</item>
+     <item type="dimen" format="float" name="spot_shadow_alpha">0.3</item>
 
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d8b129c..a798d2e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4172,10 +4172,6 @@
         <attr name="completionThreshold" format="integer" min="1" />
         <!-- Selector in a drop down list. -->
         <attr name="dropDownSelector" format="reference|color" />
-        <!-- Amount of pixels by which the drop down should be offset vertically. -->
-        <attr name="dropDownVerticalOffset" format="dimension" />
-        <!-- Amount of pixels by which the drop down should be offset horizontally. -->
-        <attr name="dropDownHorizontalOffset" format="dimension" />
         <!-- View to anchor the auto-complete dropdown to. If not specified, the text view itself
              is used. -->
         <attr name="dropDownAnchor" format="reference" />
@@ -4223,6 +4219,12 @@
         <!-- Whether the popup window should overlap its anchor view. -->
         <attr name="overlapAnchor" format="boolean" />
     </declare-styleable>
+    <declare-styleable name="ListPopupWindow">
+        <!-- Amount of pixels by which the drop down should be offset vertically. -->
+        <attr name="dropDownVerticalOffset" format="dimension" />
+        <!-- Amount of pixels by which the drop down should be offset horizontally. -->
+        <attr name="dropDownHorizontalOffset" format="dimension" />
+    </declare-styleable>
     <declare-styleable name="ViewAnimator">
         <!-- Identifier for the animation to use when a view is shown. -->
         <attr name="inAnimation" format="reference" />
@@ -4281,12 +4283,6 @@
         <attr name="popupBackground" />
         <!-- Window elevation to use for the dropdown in spinnerMode="dropdown". -->
         <attr name="popupElevation" />
-        <!-- Vertical offset from the spinner widget for positioning the dropdown in
-             spinnerMode="dropdown". -->
-        <attr name="dropDownVerticalOffset" />
-        <!-- Horizontal offset from the spinner widget for positioning the dropdown
-             in spinnerMode="dropdown". -->
-        <attr name="dropDownHorizontalOffset" />
         <!-- Width of the dropdown in spinnerMode="dropdown". -->
         <attr name="dropDownWidth" />
         <!-- Reference to a layout to use for displaying a prompt in the dropdown for
@@ -7322,6 +7318,12 @@
         <!-- Reference to a theme that should be used to inflate popups
              shown by widgets in the toolbar. -->
         <attr name="popupTheme" format="reference" />
+        <!-- Icon drawable to use for the navigation button located at
+             the start of the toolbar. -->
+        <attr name="navigationIcon" format="reference" />
+        <!-- Text to set as the content description for the navigation button
+             located at the start of the toolbar. -->
+        <attr name="navigationContentDescription" format="string" />
     </declare-styleable>
 
     <declare-styleable name="Toolbar_LayoutParams">
@@ -7348,14 +7350,15 @@
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. -->
         <attr name="settingsActivity" />
-        <!-- Reference to an XML document that describes TV content rating. -->
-        <attr name="tvContentRatingDescription" format="reference" />
     </declare-styleable>
 
+    <!-- @removed -->
+    <attr name="__removed1" format="reference" />
+
     <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
-         XML resource that describes TV content rating of a
-         {@link android.media.tv.TvInputService}, which is referenced from
-         {@link android.R.attr#tvContentRatingDescription}. -->
+         XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
+         which is referenced from its
+         {@link android.media.tv.TvInputManager#META_DATA_CONTENT_RATING_SYSTEMS}. -->
     <declare-styleable name="RatingSystemDefinition">
         <!-- The unique name of the content rating system. -->
         <attr name="name" />
@@ -7363,13 +7366,15 @@
         <attr name="title" />
         <!-- The short description of the content rating system. -->
         <attr name="description" />
-        <!-- The country associated with the content rating system. -->
+        <!-- The country code associated with the content rating system, which consists of two
+             uppercase letters that conform to the ISO 3166 standard. -->
         <attr name="country" format="string" />
     </declare-styleable>
 
     <!-- Attributes that can be used with <code>rating-definition</code> tags inside of the XML
          resource that describes TV content rating of a {@link android.media.tv.TvInputService},
-         which is referenced from {@link android.R.attr#tvContentRatingDescription}. -->
+         which is referenced from its
+         {@link android.media.tv.TvInputManager#META_DATA_CONTENT_RATING_SYSTEMS}. -->
     <declare-styleable name="RatingDefinition">
         <!-- The unique name of the content rating. -->
         <attr name="name" />
@@ -7379,7 +7384,7 @@
         <attr name="description" />
         <!-- The age associated with the content rating. The content of this rating is suitable for
              people of this age or above. -->
-        <attr name="ageHint" format="integer" />
+        <attr name="contentAgeHint" format="integer" />
     </declare-styleable>
 
     <declare-styleable name="ResolverDrawerLayout">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4f0757c..af213ba 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -26,6 +26,7 @@
        <item><xliff:g id="id">ime</xliff:g></item>
        <item><xliff:g id="id">sync_failing</xliff:g></item>
        <item><xliff:g id="id">sync_active</xliff:g></item>
+       <item><xliff:g id="id">cast</xliff:g></item>
        <item><xliff:g id="id">location</xliff:g></item>
        <item><xliff:g id="id">bluetooth</xliff:g></item>
        <item><xliff:g id="id">nfc</xliff:g></item>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4e3abb9..77b451f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -236,6 +236,9 @@
     <!-- Padding for notification icon when drawn with circle around it -->
     <dimen name="notification_large_icon_circle_padding">11dp</dimen>
 
+    <!-- Size of the profile badge for notifications -->
+    <dimen name="notification_badge_size">16dp</dimen>
+
     <!-- Keyguard dimensions -->
     <!-- TEMP -->
     <dimen name="kg_security_panel_height">600dp</dimen>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 972ae5e..f5c9299 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -33,7 +33,6 @@
 
     <dimen name="action_button_min_width_material">48dp</dimen>
     <dimen name="action_button_min_height_material">48dp</dimen>
-    <dimen name="action_overflow_min_width_material">36dp</dimen>
 
     <dimen name="text_size_display_4_material">112sp</dimen>
     <dimen name="text_size_display_3_material">56sp</dimen>
@@ -64,6 +63,13 @@
     <dimen name="button_elevation_material">1dp</dimen>
     <!-- Z translation to apply when button is pressed -->
     <dimen name="button_pressed_z_material">2dp</dimen>
+    <!-- Default insets (outer padding) around buttons -->
+    <dimen name="button_inset_vertical_material">6dp</dimen>
+    <dimen name="button_inset_horizontal_material">@dimen/control_inset_material</dimen>
+    <!-- Default inner padding within buttons -->
+    <dimen name="button_padding_vertical_material">@dimen/control_padding_material</dimen>
+    <dimen name="button_padding_horizontal_material">8dp</dimen>
+
     <!-- Default insets (outer padding) around controls -->
     <dimen name="control_inset_material">4dp</dimen>
     <!-- Default inner padding within controls -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 82125fe..d452739 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2266,20 +2266,22 @@
   <public type="attr" name="windowReenterTransition" />
   <public type="attr" name="windowSharedElementReturnTransition" />
   <public type="attr" name="windowSharedElementReenterTransition" />
-  <public type="attr" name="tvContentRatingDescription"/>
+  <public type="attr" name="__removed1" />
   <public type="attr" name="datePickerMode"/>
   <public type="attr" name="timePickerMode"/>
   <public type="attr" name="inset" />
   <public type="attr" name="letterSpacing" />
   <public type="attr" name="fontFeatureSettings" />
   <public type="attr" name="outlineProvider" />
-  <public type="attr" name="ageHint" />
+  <public type="attr" name="contentAgeHint" />
   <public type="attr" name="country" />
   <public type="attr" name="windowSharedElementsUseOverlay" />
   <public type="attr" name="reparent" />
   <public type="attr" name="reparentWithOverlay" />
   <public type="attr" name="ambientShadowAlpha" />
   <public type="attr" name="spotShadowAlpha" />
+  <public type="attr" name="navigationIcon" />
+  <public type="attr" name="navigationContentDescription" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2527,20 +2529,25 @@
 
   <public type="style" name="Theme.Leanback.FormWizard"/>
 
-  <public type="style" name="TextAppearance.StatusBar.Material" />
-  <public type="style" name="TextAppearance.StatusBar.Material.EventContent" />
-  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Title" />
-  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Line2" />
-  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Info" />
-  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Time" />
-  <public type="style" name="TextAppearance.StatusBar.Material.EventContent.Emphasis" />
+  <public type="style" name="__removed" />
+  <public type="style" name="TextAppearance.Material.Notification" />
+  <public type="style" name="TextAppearance.Material.Notification.Title" />
+  <public type="style" name="TextAppearance.Material.Notification.Line2" />
+  <public type="style" name="TextAppearance.Material.Notification.Info" />
+  <public type="style" name="TextAppearance.Material.Notification.Time" />
+  <public type="style" name="TextAppearance.Material.Notification.Emphasis" />
 
-  <public type="style" name="Widget.Material.Spinner.Form" />
-  <public type="style" name="Widget.Material.Light.Spinner.Form" />
+  <public type="style" name="Widget.Material.Spinner.Underlined" />
+  <public type="style" name="Widget.Material.Light.Spinner.Underlined" />
 
   <public type="style" name="TextAppearance.Material.Widget.Toolbar.Title" />
   <public type="style" name="TextAppearance.Material.Widget.Toolbar.Subtitle" />
 
+  <public type="style" name="Theme.Material.Dialog.Alert" />
+  <public type="style" name="Theme.Material.Dialog.Presentation" />
+  <public type="style" name="Theme.Material.Light.Dialog.Alert" />
+  <public type="style" name="Theme.Material.Light.Dialog.Presentation" />
+
   <public-padding type="string" name="l_resource_pad" end="0x01040030" />
 
   <public type="string" name="config_webSettingsDefaultTextEncoding" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d6224da..f1ec5d2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3642,9 +3642,9 @@
     <!-- The message text for the SMS short code confirmation dialog. [CHAR LIMIT=NONE] -->
     <string name="sms_short_code_confirm_message">&lt;b><xliff:g id="app_name">%1$s</xliff:g>&lt;/b> would like to send a message to &lt;b><xliff:g id="dest_address">%2$s</xliff:g>&lt;/b>.</string>
     <!-- Message details for the SMS short code confirmation dialog (possible premium short code). [CHAR LIMIT=NONE] -->
-    <string name="sms_short_code_details">This <font fgcolor="#ffffb060">may cause charges</font> on your mobile account.</string>
+    <string name="sms_short_code_details">This <b>may cause charges</b> on your mobile account.</string>
     <!-- Message details for the SMS short code confirmation dialog (premium short code). [CHAR LIMIT=NONE] -->
-    <string name="sms_premium_short_code_details"><font fgcolor="#ffffb060">This will cause charges on your mobile account.</font></string>
+    <string name="sms_premium_short_code_details"><b>This will cause charges on your mobile account.</b></string>
     <!-- Text of the approval button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
     <string name="sms_short_code_confirm_allow">Send</string>
     <!-- Text of the cancel button for the SMS short code confirmation dialog. [CHAR LIMIT=30] -->
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index fb70d6b..e783cd6 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -306,9 +306,9 @@
     </style>
 
     <style name="TextAppearance.Material.Widget.TextView.PopupMenu" parent="TextAppearance.Material.Menu" />
-    <style name="TextAppearance.Material.Widget.TextView.SpinnerItem" />
+    <style name="TextAppearance.Material.Widget.TextView.SpinnerItem" parent="TextAppearance.Material.Menu" />
 
-    <style name="TextAppearance.Material.Widget.DropDownItem">
+    <style name="TextAppearance.Material.Widget.DropDownItem" parent="TextAppearance.Material.Menu">
         <item name="textColor">?attr/textColorPrimaryDisableOnly</item>
     </style>
 
@@ -410,37 +410,35 @@
         <item name="textSize">@dimen/datepicker_year_label_text_size</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material" />
-
-    <style name="TextAppearance.StatusBar.Material.EventContent">
+    <style name="TextAppearance.Material.Notification">
         <item name="textColor">@color/secondary_text_material_light</item>
         <item name="textSize">@dimen/notification_text_size</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material.EventContent.Title">
+    <style name="TextAppearance.Material.Notification.Title">
         <item name="textColor">@color/primary_text_default_material_light</item>
         <item name="textSize">@dimen/notification_title_text_size</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material.EventContent.Line2">
+    <style name="TextAppearance.Material.Notification.Line2">
         <item name="textSize">@dimen/notification_subtext_size</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material.EventContent.Info">
+    <style name="TextAppearance.Material.Notification.Info">
         <item name="textSize">@dimen/notification_subtext_size</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material.EventContent.Time">
+    <style name="TextAppearance.Material.Notification.Time">
         <item name="textSize">@dimen/notification_subtext_size</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material.EventContent.Emphasis">
+    <style name="TextAppearance.Material.Notification.Emphasis">
         <item name="textColor">#66000000</item>
     </style>
 
-    <style name="Widget.StatusBar.Material.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
+    <style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
 
-    <style name="Widget.StatusBar.Material.ProgressBar.Media">
+    <style name="Widget.Material.Notification.ProgressBar.Media">
         <item name="progressDrawable">@drawable/notification_material_media_progress</item>
     </style>
 
@@ -746,6 +744,7 @@
         <item name="popupElevation">@dimen/floating_window_z</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
+        <item name="overlapAnchor">true</item>
         <item name="dropDownWidth">wrap_content</item>
         <item name="popupPromptView">@layout/simple_dropdown_hint</item>
         <item name="gravity">start|center_vertical</item>
@@ -759,7 +758,7 @@
         <item name="overlapAnchor">true</item>
     </style>
 
-    <style name="Widget.Material.Spinner.Form">
+    <style name="Widget.Material.Spinner.Underlined">
         <item name="background">@drawable/spinner_textfield_background_material</item>
     </style>
 
@@ -829,6 +828,7 @@
 
     <style name="Widget.Material.PopupMenu.Overflow">
         <item name="overlapAnchor">true</item>
+        <item name="dropDownHorizontalOffset">-4dip</item>
     </style>
 
     <style name="Widget.Material.ActionButton" parent="Widget.ActionButton">
@@ -837,6 +837,8 @@
         <item name="gravity">center</item>
         <item name="scaleType">center</item>
         <item name="maxLines">2</item>
+        <item name="paddingStart">0dp</item>
+        <item name="paddingEnd">0dp</item>
     </style>
 
     <style name="Widget.Material.ActionButton.CloseMode">
@@ -847,8 +849,9 @@
         <item name="src">@drawable/ic_menu_moreoverflow_material</item>
         <item name="background">?attr/actionBarItemBackground</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
-        <item name="minWidth">@dimen/action_overflow_min_width_material</item>
+        <item name="minWidth">@dimen/action_button_min_width_material</item>
         <item name="minHeight">@dimen/action_button_min_height_material</item>
+        <item name="paddingEnd">12dp</item>
         <item name="scaleType">center</item>
     </style>
 
@@ -1022,7 +1025,7 @@
     <style name="Widget.Material.Light.Spinner" parent="Widget.Material.Spinner" />
     <style name="Widget.Material.Light.Spinner.DropDown" parent="Widget.Material.Spinner.DropDown"/>
     <style name="Widget.Material.Light.Spinner.DropDown.ActionBar" parent="Widget.Material.Spinner.DropDown.ActionBar"/>
-    <style name="Widget.Material.Light.Spinner.Form" parent="Widget.Material.Spinner.Form" />
+    <style name="Widget.Material.Light.Spinner.Underlined" parent="Widget.Material.Spinner.Underlined" />
     <style name="Widget.Material.Light.TabWidget" parent="Widget.Material.TabWidget"/>
     <style name="Widget.Material.Light.WebTextView" parent="Widget.Material.WebTextView"/>
     <style name="Widget.Material.Light.WebView" parent="Widget.Material.WebView"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d8c29b0..622a01a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -357,6 +357,7 @@
   <java-symbol type="dimen" name="notification_top_pad_large_text" />
   <java-symbol type="dimen" name="notification_top_pad_large_text_narrow" />
   <java-symbol type="dimen" name="notification_large_icon_circle_padding" />
+  <java-symbol type="dimen" name="notification_badge_size" />
   <java-symbol type="dimen" name="immersive_mode_cling_width" />
   <java-symbol type="dimen" name="circular_display_mask_offset" />
 
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index a79bd0a..89fac13 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1257,4 +1257,6 @@
         <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
+    <!-- TODO: Spacer to be removed from here and public.xml -->
+    <style name="__removed" />
 </resources>
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 0f0281b..c4a949f 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    NOTE: this file is the legacy format, for compatibility with apps. The new,
+    more flexible format is fonts.xml. Please keep the two in sync until the legacy
+    format can be fully removed.
+
     Fallback Fonts
 
     This file specifies the fonts, and the priority order, that will be searched for any
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index a4d49069..04bc67a 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1,4 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+    NOTE: this is the newer (L) version of the system font configuration,
+    supporting richer weight selection. Some apps will expect the older
+    version, so please keep system_fonts.xml and fallback_fonts.xml in sync
+    with any changes, even though framework will only read this file.
+
+    All fonts withohut names are added to the default list. Fonts are chosen
+    based on a match: full BCP-47 language tag including script, then just
+    language, and finally order (the first font containing the glyph).
+
+    Order of appearance is also the tiebreaker for weight matching. This is
+    the reason why the 900 weights of Roboto precede the 700 weights - we
+    prefer the former when an 800 weight is requested. Since bold spans
+    effectively add 300 to the weight, this ensures that 900 is the bold
+    paired with the 500 weight, ensuring adequate contrast.
+-->
 <familyset version="22">
     <!-- first font is default -->
     <family name="sans-serif">
@@ -10,15 +26,16 @@
         <font weight="400" style="italic">Roboto-Italic.ttf</font>
         <font weight="500" style="normal">Roboto-Medium.ttf</font>
         <font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
-        <font weight="700" style="normal">Roboto-Bold.ttf</font>
-        <font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
         <font weight="900" style="normal">Roboto-Black.ttf</font>
         <font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
+        <font weight="700" style="normal">Roboto-Bold.ttf</font>
+        <font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
     </family>
 
     <!-- Note that aliases must come after the fonts they reference. -->
     <alias name="sans-serif-thin" to="sans-serif" weight="100" />
     <alias name="sans-serif-light" to="sans-serif" weight="300" />
+    <alias name="sans-serif-medium" to="sans-serif" weight="500" />
     <alias name="sans-serif-black" to="sans-serif" weight="900" />
     <alias name="arial" to="sans-serif" />
     <alias name="helvetica" to="sans-serif" />
@@ -227,6 +244,9 @@
     <family>
         <font weight="400" style="normal">NotoColorEmoji.ttf</font>
     </family>
+    <family>
+        <font weight="400" style="normal">DroidSansFallback.ttf</font>
+    </family>
     <family lang="ja">
         <font weight="400" style="normal">MTLmr3m.ttf</font>
     </family>
diff --git a/data/sounds/AudioPackage13.mk b/data/sounds/AudioPackage13.mk
index 57fe762..9bbfa7f 100644
--- a/data/sounds/AudioPackage13.mk
+++ b/data/sounds/AudioPackage13.mk
@@ -8,12 +8,10 @@
 LOCAL_PATH := frameworks/base/data/sounds
 
 # Simple files that do not require renaming
-ALARM_FILES := Alarm1 Alarm2 Alarm3 Alarm4 Alarm5 Alarm6 Alarm7 Alarm8 Timer
-NOTIFICATION_FILES := Notification1 Notification2 Notification3 Notification4 \
-	Notification5 Notification6 Notification7 Notification8 Notification9 \
-	Notification10 Notification11
-RINGTONE_FILES := Ringtone1 Ringtone2 Ringtone3 Ringtone4 Ringtone5 Ringtone6 \
-	Ringtone7 Ringtone8 Ringtone9 Ringtone10 Ringtone11 Ringtone12
+ALARM_FILES := Argon Carbon Helium Krypton Neon Oxygen Osmium Platinum Timer
+NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
+RINGTONE_FILES := Atria Callisto Dione Ganymede Luna Oberon Phobos Pyxis Sedna Titania Triton \
+	Umbriel
 EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
 	camera_click camera_focus Dock Undock Lock Unlock Trusted
 MATERIAL_EFFECT_FILES := VideoRecord WirelessChargingStarted LowBattery
diff --git a/data/sounds/AudioPackage13_48.mk b/data/sounds/AudioPackage13_48.mk
index 187bccb..b90cd00 100644
--- a/data/sounds/AudioPackage13_48.mk
+++ b/data/sounds/AudioPackage13_48.mk
@@ -8,12 +8,10 @@
 LOCAL_PATH := frameworks/base/data/sounds
 
 # Simple files that do not require renaming
-ALARM_FILES := Alarm1 Alarm2 Alarm3 Alarm4 Alarm5 Alarm6 Alarm7 Alarm8 Timer
-NOTIFICATION_FILES := Notification1 Notification2 Notification3 Notification4 \
-	Notification5 Notification6 Notification7 Notification8 Notification9 \
-	Notification10 Notification11
-RINGTONE_FILES := Ringtone1 Ringtone2 Ringtone3 Ringtone4 Ringtone5 Ringtone6 \
-	Ringtone7 Ringtone8 Ringtone9 Ringtone10 Ringtone11 Ringtone12
+ALARM_FILES := Argon Carbon Helium Krypton Neon Oxygen Osmium Platinum Timer
+NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
+RINGTONE_FILES := Atria Callisto Dione Ganymede Luna Oberon Phobos Pyxis Sedna Titania Triton \
+	Umbriel
 EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
 	camera_click Lock Unlock Trusted
 MATERIAL_EFFECT_FILES := VideoRecord WirelessChargingStarted LowBattery
diff --git a/data/sounds/alarms/material/ogg/Alarm1.ogg b/data/sounds/alarms/material/ogg/Argon.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm1.ogg
rename to data/sounds/alarms/material/ogg/Argon.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm1_48k.ogg b/data/sounds/alarms/material/ogg/Argon_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm1_48k.ogg
rename to data/sounds/alarms/material/ogg/Argon_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm2.ogg b/data/sounds/alarms/material/ogg/Carbon.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm2.ogg
rename to data/sounds/alarms/material/ogg/Carbon.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm2_48k.ogg b/data/sounds/alarms/material/ogg/Carbon_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm2_48k.ogg
rename to data/sounds/alarms/material/ogg/Carbon_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm3.ogg b/data/sounds/alarms/material/ogg/Helium.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm3.ogg
rename to data/sounds/alarms/material/ogg/Helium.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm3_48k.ogg b/data/sounds/alarms/material/ogg/Helium_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm3_48k.ogg
rename to data/sounds/alarms/material/ogg/Helium_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm4.ogg b/data/sounds/alarms/material/ogg/Krypton.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm4.ogg
rename to data/sounds/alarms/material/ogg/Krypton.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm4_48k.ogg b/data/sounds/alarms/material/ogg/Krypton_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm4_48k.ogg
rename to data/sounds/alarms/material/ogg/Krypton_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm5.ogg b/data/sounds/alarms/material/ogg/Neon.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm5.ogg
rename to data/sounds/alarms/material/ogg/Neon.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm5_48k.ogg b/data/sounds/alarms/material/ogg/Neon_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm5_48k.ogg
rename to data/sounds/alarms/material/ogg/Neon_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm6.ogg b/data/sounds/alarms/material/ogg/Osmium.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm6.ogg
rename to data/sounds/alarms/material/ogg/Osmium.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm6_48k.ogg b/data/sounds/alarms/material/ogg/Osmium_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm6_48k.ogg
rename to data/sounds/alarms/material/ogg/Osmium_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm7.ogg b/data/sounds/alarms/material/ogg/Oxygen.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm7.ogg
rename to data/sounds/alarms/material/ogg/Oxygen.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm7_48k.ogg b/data/sounds/alarms/material/ogg/Oxygen_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm7_48k.ogg
rename to data/sounds/alarms/material/ogg/Oxygen_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm8.ogg b/data/sounds/alarms/material/ogg/Platinum.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm8.ogg
rename to data/sounds/alarms/material/ogg/Platinum.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm8_48k.ogg b/data/sounds/alarms/material/ogg/Platinum_48k.ogg
similarity index 100%
rename from data/sounds/alarms/material/ogg/Alarm8_48k.ogg
rename to data/sounds/alarms/material/ogg/Platinum_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification3.ogg b/data/sounds/notifications/material/ogg/Ariel.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification3.ogg
rename to data/sounds/notifications/material/ogg/Ariel.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification3_48k.ogg b/data/sounds/notifications/material/ogg/Ariel_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification3_48k.ogg
rename to data/sounds/notifications/material/ogg/Ariel_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification4.ogg b/data/sounds/notifications/material/ogg/Carme.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification4.ogg
rename to data/sounds/notifications/material/ogg/Carme.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification4_48k.ogg b/data/sounds/notifications/material/ogg/Carme_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification4_48k.ogg
rename to data/sounds/notifications/material/ogg/Carme_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification5.ogg b/data/sounds/notifications/material/ogg/Ceres.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification5.ogg
rename to data/sounds/notifications/material/ogg/Ceres.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification5_48k.ogg b/data/sounds/notifications/material/ogg/Ceres_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification5_48k.ogg
rename to data/sounds/notifications/material/ogg/Ceres_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification6.ogg b/data/sounds/notifications/material/ogg/Elara.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification6.ogg
rename to data/sounds/notifications/material/ogg/Elara.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification6_48k.ogg b/data/sounds/notifications/material/ogg/Elara_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification6_48k.ogg
rename to data/sounds/notifications/material/ogg/Elara_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification7.ogg b/data/sounds/notifications/material/ogg/Europa.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification7.ogg
rename to data/sounds/notifications/material/ogg/Europa.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification7_48k.ogg b/data/sounds/notifications/material/ogg/Europa_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification7_48k.ogg
rename to data/sounds/notifications/material/ogg/Europa_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification8.ogg b/data/sounds/notifications/material/ogg/Iapetus.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification8.ogg
rename to data/sounds/notifications/material/ogg/Iapetus.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification8_48k.ogg b/data/sounds/notifications/material/ogg/Iapetus_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification8_48k.ogg
rename to data/sounds/notifications/material/ogg/Iapetus_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification9.ogg b/data/sounds/notifications/material/ogg/Io.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification9.ogg
rename to data/sounds/notifications/material/ogg/Io.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification9_48k.ogg b/data/sounds/notifications/material/ogg/Io_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification9_48k.ogg
rename to data/sounds/notifications/material/ogg/Io_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification10.ogg b/data/sounds/notifications/material/ogg/Rhea.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification10.ogg
rename to data/sounds/notifications/material/ogg/Rhea.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification10_48k.ogg b/data/sounds/notifications/material/ogg/Rhea_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification10_48k.ogg
rename to data/sounds/notifications/material/ogg/Rhea_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification11.ogg b/data/sounds/notifications/material/ogg/Salacia.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification11.ogg
rename to data/sounds/notifications/material/ogg/Salacia.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification11_48k.ogg b/data/sounds/notifications/material/ogg/Salacia_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification11_48k.ogg
rename to data/sounds/notifications/material/ogg/Salacia_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification1.ogg b/data/sounds/notifications/material/ogg/Tethys.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification1.ogg
rename to data/sounds/notifications/material/ogg/Tethys.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification1_48k.ogg b/data/sounds/notifications/material/ogg/Tethys_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification1_48k.ogg
rename to data/sounds/notifications/material/ogg/Tethys_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification2.ogg b/data/sounds/notifications/material/ogg/Titan.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification2.ogg
rename to data/sounds/notifications/material/ogg/Titan.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification2_48k.ogg b/data/sounds/notifications/material/ogg/Titan_48k.ogg
similarity index 100%
rename from data/sounds/notifications/material/ogg/Notification2_48k.ogg
rename to data/sounds/notifications/material/ogg/Titan_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone4.ogg b/data/sounds/ringtones/material/ogg/Atria.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone4.ogg
rename to data/sounds/ringtones/material/ogg/Atria.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg b/data/sounds/ringtones/material/ogg/Atria_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg
rename to data/sounds/ringtones/material/ogg/Atria_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone5.ogg b/data/sounds/ringtones/material/ogg/Callisto.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone5.ogg
rename to data/sounds/ringtones/material/ogg/Callisto.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg b/data/sounds/ringtones/material/ogg/Callisto_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg
rename to data/sounds/ringtones/material/ogg/Callisto_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone6.ogg b/data/sounds/ringtones/material/ogg/Dione.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone6.ogg
rename to data/sounds/ringtones/material/ogg/Dione.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg b/data/sounds/ringtones/material/ogg/Dione_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg
rename to data/sounds/ringtones/material/ogg/Dione_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone7.ogg b/data/sounds/ringtones/material/ogg/Ganymede.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone7.ogg
rename to data/sounds/ringtones/material/ogg/Ganymede.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg b/data/sounds/ringtones/material/ogg/Ganymede_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg
rename to data/sounds/ringtones/material/ogg/Ganymede_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone8.ogg b/data/sounds/ringtones/material/ogg/Luna.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone8.ogg
rename to data/sounds/ringtones/material/ogg/Luna.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg b/data/sounds/ringtones/material/ogg/Luna_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg
rename to data/sounds/ringtones/material/ogg/Luna_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone9.ogg b/data/sounds/ringtones/material/ogg/Oberon.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone9.ogg
rename to data/sounds/ringtones/material/ogg/Oberon.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg b/data/sounds/ringtones/material/ogg/Oberon_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg
rename to data/sounds/ringtones/material/ogg/Oberon_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone10.ogg b/data/sounds/ringtones/material/ogg/Phobos.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone10.ogg
rename to data/sounds/ringtones/material/ogg/Phobos.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg b/data/sounds/ringtones/material/ogg/Phobos_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg
rename to data/sounds/ringtones/material/ogg/Phobos_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone11.ogg b/data/sounds/ringtones/material/ogg/Pyxis.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone11.ogg
rename to data/sounds/ringtones/material/ogg/Pyxis.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg b/data/sounds/ringtones/material/ogg/Pyxis_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg
rename to data/sounds/ringtones/material/ogg/Pyxis_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone12.ogg b/data/sounds/ringtones/material/ogg/Sedna.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone12.ogg
rename to data/sounds/ringtones/material/ogg/Sedna.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg b/data/sounds/ringtones/material/ogg/Sedna_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg
rename to data/sounds/ringtones/material/ogg/Sedna_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone1.ogg b/data/sounds/ringtones/material/ogg/Titania.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone1.ogg
rename to data/sounds/ringtones/material/ogg/Titania.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg b/data/sounds/ringtones/material/ogg/Titania_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg
rename to data/sounds/ringtones/material/ogg/Titania_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone2.ogg b/data/sounds/ringtones/material/ogg/Triton.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone2.ogg
rename to data/sounds/ringtones/material/ogg/Triton.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg b/data/sounds/ringtones/material/ogg/Triton_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg
rename to data/sounds/ringtones/material/ogg/Triton_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone3.ogg b/data/sounds/ringtones/material/ogg/Umbriel.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone3.ogg
rename to data/sounds/ringtones/material/ogg/Umbriel.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg b/data/sounds/ringtones/material/ogg/Umbriel_48k.ogg
similarity index 100%
rename from data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg
rename to data/sounds/ringtones/material/ogg/Umbriel_48k.ogg
Binary files differ
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 45e2fed..1e32d43 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -1,3 +1,10 @@
+# WARNING: THIS FILE IS NOT USED IN PRODUCTION
+# CHANGES MADE HERE **DO NOT EFFECT** developer.android.com
+
+# Instead, update the following file in the current docs release branch:
+# <docs-release-branch>/vendor/google/docs/app-engine-server/v3/redirects.yaml
+
+#=============================================================================
 # Redirects file.
 # This file contains the list of rewrite rules that are applied when serving
 # pages. Add "pattern: True" to use python regex in to or from.
diff --git a/docs/html/google/play-services/setup.jd b/docs/html/google/play-services/setup.jd
index ebd3694..d7e449b 100644
--- a/docs/html/google/play-services/setup.jd
+++ b/docs/html/google/play-services/setup.jd
@@ -66,8 +66,8 @@
 ...
 
 dependencies {
-    compile 'com.android.support:appcompat-v7:+'
-    <strong>compile 'com.google.android.gms:play-services:5.0.77'</strong>
+    compile 'com.android.support:appcompat-v7:20.+'
+    <strong>compile 'com.google.android.gms:play-services:5.+'</strong>
 }
 </pre>
 <p>Be sure you update this version number each time Google Play services is updated.</p>
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 851827c..5a433d4 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -104,7 +104,7 @@
   </tr>
   <tr>
     <td>
-      <a href="http://dl.google.com/android/{@adtZipDownload}">{@adtZipDownload}</a>
+      <a href="https://dl.google.com/android/{@adtZipDownload}">{@adtZipDownload}</a>
     </td>
     <td>{@adtZipBytes} bytes</td>
     <td>{@adtZipChecksum}</td>
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 71d6c1c..ee14b19 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -251,7 +251,7 @@
     <td>Windows</td>
     <td>
   <a onclick="return onDownload(this)" id="win-studio"
-      href="http://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-windows.exe">
+      href="https://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-windows.exe">
       android-studio-bundle-135.1339820-windows.exe
       </a>
     </td>
@@ -263,7 +263,7 @@
     <td><nobr>Mac OS X</nobr></td>
     <td>
   <a onclick="return onDownload(this)" id="mac-studio"
-    href="http://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-mac.dmg">
+    href="https://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-mac.dmg">
     android-studio-bundle-135.1339820-mac.dmg
     </a>
     </td>
@@ -275,7 +275,7 @@
     <td>Linux</td>
     <td>
   <a onclick="return onDownload(this)" id="linux-studio"
-    href="http://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-linux.tgz">
+    href="https://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-linux.tgz">
     android-studio-bundle-135.1339820-linux.tgz
     </a>
     </td>
diff --git a/docs/html/training/wearables/notifications/creating.jd b/docs/html/training/wearables/notifications/creating.jd
index d6ad34a..9398f96 100644
--- a/docs/html/training/wearables/notifications/creating.jd
+++ b/docs/html/training/wearables/notifications/creating.jd
@@ -208,9 +208,12 @@
         <b>.setStyle(bigStyle);</b>
 </pre>
 
-<p>Notice that you can add a large background image to any notification using the
+<p>Notice that you can add a large icon image to any notification using the
 {@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon setLargeIcon()}
-method. For more information about designing notifications with large images, see the
+method. However, these icons appear as large background images on a wearable and do not look
+good as they are scaled up to fit the wearable screen. To add a wearable-specific background image
+to a notification, see <a href="#AddWearableFeatures">Add Wearable Features For a Notification</a>.
+For more information about designing notifications with large images, see the
 <a href="{@docRoot}design/wear/index.html">Design Principles of Android
 Wear</a>.</p>
 
@@ -244,7 +247,8 @@
 // Create a WearableExtender to add functionality for wearables
 NotificationCompat.WearableExtender wearableExtender =
         new NotificationCompat.WearableExtender()
-        .setHintHideIcon(true);
+        .setHintHideIcon(true)
+        .setBackground(mBitmap);
 
 // Create a NotificationCompat.Builder to build a standard notification
 // then extend it with the WearableExtender
@@ -257,12 +261,21 @@
 </pre>
 
 <p>The
-  {@link android.support.v4.app.NotificationCompat.WearableExtender#setHintHideIcon setHintHideIcon()}
-  method is just one example of new notification features available with
-  {@link android.support.v4.app.NotificationCompat.WearableExtender}.
-</p>
+{@link android.support.v4.app.NotificationCompat.WearableExtender#setHintHideIcon setHintHideIcon()}
+and {@link android.support.v4.app.NotificationCompat.WearableExtender#setBackground setBackground()}
+methods are just two examples of new notification features available with
+{@link android.support.v4.app.NotificationCompat.WearableExtender}.</p>
 
-<p>If you ever need to read wearable-specifc options at a later time, use the corresponding get
+<p class="note"><strong>Note:</strong> The bitmap that you use with
+{@link android.support.v4.app.NotificationCompat.WearableExtender#setBackground setBackground()}
+should have a resolution of 400x400 for non-scrolling backgrounds and 640x400 for backgrounds
+that support parallax scrolling. Place these bitmap images in the <code>res/drawable-nodpi</code>
+directory of your handheld app. Place other non-bitmap resources for wearable notifications, such
+as those used with the
+{@link android.support.v4.app.NotificationCompat.WearableExtender#setContentIcon setContentIcon()}
+method, in the <code>res/drawable-hdpi</code> directory of your handheld app.</p>
+
+<p>If you ever need to read wearable-specific options at a later time, use the corresponding get
 method for the option. This example calls the
 {@link android.support.v4.app.NotificationCompat.WearableExtender#getHintHideIcon()} method to
 get whether or not this notification hides the icon:
@@ -272,6 +285,7 @@
 boolean hintHideIcon = wearableExtender.getHintHideIcon();
 </pre>
 
+
 <h2 id="Deliver">Deliver the Notification</h2>
 <p>When you want to deliver your notifications, always use the
   {@link android.support.v4.app.NotificationManagerCompat} API instead of
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 11d3165..b8b7e76 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -18,8 +18,6 @@
 
 import android.content.res.AssetManager;
 
-import java.io.File;
-
 /**
  * A family of typefaces with different styles.
  *
@@ -64,6 +62,10 @@
         return nAddFont(mNativePtr, path);
     }
 
+    public boolean addFontWeightStyle(String path, int weight, boolean style) {
+        return nAddFontWeightStyle(mNativePtr, path, weight, style);
+    }
+
     public boolean addFontFromAsset(AssetManager mgr, String path) {
         return nAddFontFromAsset(mNativePtr, mgr, path);
     }
@@ -71,6 +73,8 @@
     private static native long nCreateFamily(String lang, int variant);
     private static native void nUnrefFamily(long nativePtr);
     private static native boolean nAddFont(long nativeFamily, String path);
+    private static native boolean nAddFontWeightStyle(long nativeFamily, String path,
+            int weight, boolean isItalic);
     private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr,
             String path);
 }
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index a863a06..97081f9 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -33,23 +33,48 @@
  */
 public class FontListParser {
 
+    public static class Config {
+        Config() {
+            families = new ArrayList<Family>();
+            aliases = new ArrayList<Alias>();
+        }
+        public List<Family> families;
+        public List<Alias> aliases;
+    }
+
+    public static class Font {
+        Font(String fontName, int weight, boolean isItalic) {
+            this.fontName = fontName;
+            this.weight = weight;
+            this.isItalic = isItalic;
+        }
+        public String fontName;
+        public int weight;
+        public boolean isItalic;
+    }
+
+    public static class Alias {
+        public String name;
+        public String toName;
+        public int weight;
+    }
+
     public static class Family {
-        public Family(List<String> names, List<String> fontFiles, String lang, String variant) {
-            this.names = names;
-            this.fontFiles = fontFiles;
+        public Family(String name, List<Font> fonts, String lang, String variant) {
+            this.name = name;
+            this.fonts = fonts;
             this.lang = lang;
             this.variant = variant;
         }
 
-        public List<String> names;
-        // todo: need attributes for font files
-        public List<String> fontFiles;
+        public String name;
+        public List<Font> fonts;
         public String lang;
         public String variant;
     }
 
     /* Parse fallback list (no names) */
-    public static List<Family> parse(InputStream in) throws XmlPullParserException, IOException {
+    public static Config parse(InputStream in) throws XmlPullParserException, IOException {
         try {
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(in, null);
@@ -60,57 +85,59 @@
         }
     }
 
-    private static List<Family> readFamilies(XmlPullParser parser)
+    private static Config readFamilies(XmlPullParser parser)
             throws XmlPullParserException, IOException {
-        List<Family> families = new ArrayList<Family>();
+        Config config = new Config();
         parser.require(XmlPullParser.START_TAG, null, "familyset");
         while (parser.next() != XmlPullParser.END_TAG) {
             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
             if (parser.getName().equals("family")) {
-                families.add(readFamily(parser));
+                config.families.add(readFamily(parser));
+            } else if (parser.getName().equals("alias")) {
+                config.aliases.add(readAlias(parser));
             } else {
                 skip(parser);
             }
         }
-        return families;
+        return config;
     }
 
     private static Family readFamily(XmlPullParser parser)
             throws XmlPullParserException, IOException {
-        List<String> names = null;
-        List<String> fontFiles = new ArrayList<String>();
-        String lang = null;
-        String variant = null;
+        String name = parser.getAttributeValue(null, "name");
+        String lang = parser.getAttributeValue(null, "lang");
+        String variant = parser.getAttributeValue(null, "variant");
+        List<Font> fonts = new ArrayList<Font>();
         while (parser.next() != XmlPullParser.END_TAG) {
             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
             String tag = parser.getName();
-            if (tag.equals("fileset")) {
-                while (parser.next() != XmlPullParser.END_TAG) {
-                    if (parser.getEventType() != XmlPullParser.START_TAG) continue;
-                    if (parser.getName().equals("file")) {
-                        if (lang == null) {
-                            lang = parser.getAttributeValue(null, "lang");
-                        }
-                        if (variant == null) {
-                            variant = parser.getAttributeValue(null, "variant");
-                        }
-                        String filename = parser.nextText();
-                        String fullFilename = "/system/fonts/" + filename;
-                        fontFiles.add(fullFilename);
-                    }
-                }
-            } else if (tag.equals("nameset")) {
-                names = new ArrayList<String>();
-                while (parser.next() != XmlPullParser.END_TAG) {
-                    if (parser.getEventType() != XmlPullParser.START_TAG) continue;
-                    if (parser.getName().equals("name")) {
-                        String name = parser.nextText();
-                        names.add(name);
-                    }
-                }
+            if (tag.equals("font")) {
+                String weightStr = parser.getAttributeValue(null, "weight");
+                int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
+                boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));
+                String filename = parser.nextText();
+                String fullFilename = "/system/fonts/" + filename;
+                fonts.add(new Font(fullFilename, weight, isItalic));
+            } else {
+                skip(parser);
             }
         }
-        return new Family(names, fontFiles, lang, variant);
+        return new Family(name, fonts, lang, variant);
+    }
+
+    private static Alias readAlias(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        Alias alias = new Alias();
+        alias.name = parser.getAttributeValue(null, "name");
+        alias.toName = parser.getAttributeValue(null, "to");
+        String weightStr = parser.getAttributeValue(null, "weight");
+        if (weightStr == null) {
+            alias.weight = 400;
+        } else {
+            alias.weight = Integer.parseInt(weightStr);
+        }
+        skip(parser);  // alias tag is empty, ignore any contents and consume end tag
+        return alias;
     }
 
     private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 568d3f2..db42314 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -66,8 +66,7 @@
     static Map<String, Typeface> sSystemFontMap;
     static FontFamily[] sFallbackFonts;
 
-    static final String SYSTEM_FONTS_CONFIG = "system_fonts.xml";
-    static final String FALLBACK_FONTS_CONFIG = "fallback_fonts.xml";
+    static final String FONTS_CONFIG = "fonts.xml";
 
     /**
      * @hide
@@ -261,10 +260,9 @@
     }
 
     private static FontFamily makeFamilyFromParsed(FontListParser.Family family) {
-        // TODO: expand to handle attributes like lang and variant
         FontFamily fontFamily = new FontFamily(family.lang, family.variant);
-        for (String fontFile : family.fontFiles) {
-            fontFamily.addFont(fontFile);
+        for (FontListParser.Font font : family.fonts) {
+            fontFamily.addFontWeightStyle(font.fontName, font.weight, font.isItalic);
         }
         return fontFamily;
     }
@@ -277,48 +275,53 @@
     private static void init() {
         // Load font config and initialize Minikin state
         File systemFontConfigLocation = getSystemFontConfigLocation();
-        File systemConfigFilename = new File(systemFontConfigLocation, SYSTEM_FONTS_CONFIG);
-        File configFilename = new File(systemFontConfigLocation, FALLBACK_FONTS_CONFIG);
+        File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
         try {
-            // TODO: throws an exception non-Minikin builds, to fail early;
-            // remove when Minikin-only
-            new FontFamily();
+            FileInputStream fontsIn = new FileInputStream(configFilename);
+            FontListParser.Config fontConfig = FontListParser.parse(fontsIn);
 
-            FileInputStream systemIn = new FileInputStream(systemConfigFilename);
-            List<FontListParser.Family> systemFontConfig = FontListParser.parse(systemIn);
-
-            FileInputStream fallbackIn = new FileInputStream(configFilename);
             List<FontFamily> familyList = new ArrayList<FontFamily>();
             // Note that the default typeface is always present in the fallback list;
             // this is an enhancement from pre-Minikin behavior.
-            familyList.add(makeFamilyFromParsed(systemFontConfig.get(0)));
-            for (Family f : FontListParser.parse(fallbackIn)) {
-                familyList.add(makeFamilyFromParsed(f));
+            for (int i = 0; i < fontConfig.families.size(); i++) {
+                Family f = fontConfig.families.get(i);
+                if (i == 0 || f.name == null) {
+                    familyList.add(makeFamilyFromParsed(f));
+                }
             }
             sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
             setDefault(Typeface.createFromFamilies(sFallbackFonts));
 
             Map<String, Typeface> systemFonts = new HashMap<String, Typeface>();
-            for (int i = 0; i < systemFontConfig.size(); i++) {
+            for (int i = 0; i < fontConfig.families.size(); i++) {
                 Typeface typeface;
-                Family f = systemFontConfig.get(i);
-                if (i == 0) {
-                    // The first entry is the default typeface; no sense in duplicating
-                    // the corresponding FontFamily.
-                    typeface = sDefaultTypeface;
-                } else {
-                    FontFamily fontFamily = makeFamilyFromParsed(f);
-                    FontFamily[] families = { fontFamily };
-                    typeface = Typeface.createFromFamiliesWithDefault(families);
+                Family f = fontConfig.families.get(i);
+                if (f.name != null) {
+                    if (i == 0) {
+                        // The first entry is the default typeface; no sense in
+                        // duplicating the corresponding FontFamily.
+                        typeface = sDefaultTypeface;
+                    } else {
+                        FontFamily fontFamily = makeFamilyFromParsed(f);
+                        FontFamily[] families = { fontFamily };
+                        typeface = Typeface.createFromFamiliesWithDefault(families);
+                    }
+                    systemFonts.put(f.name, typeface);
                 }
-                for (String name : f.names) {
-                    systemFonts.put(name, typeface);
+            }
+            for (FontListParser.Alias alias : fontConfig.aliases) {
+                Typeface base = systemFonts.get(alias.toName);
+                Typeface newFace = base;
+                int weight = alias.weight;
+                if (weight != 400) {
+                    newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
                 }
+                systemFonts.put(alias.name, newFace);
             }
             sSystemFontMap = systemFonts;
 
         } catch (RuntimeException e) {
-            Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)");
+            Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
             // TODO: normal in non-Minikin case, remove or make error when Minikin-only
         } catch (FileNotFoundException e) {
             Log.e(TAG, "Error opening " + configFilename);
@@ -383,6 +386,7 @@
     }
 
     private static native long nativeCreateFromTypeface(long native_instance, int style);
+    private static native long nativeCreateWeightAlias(long native_instance, int weight);
     private static native void nativeUnref(long native_instance);
     private static native int  nativeGetStyle(long native_instance);
     private static native long nativeCreateFromArray(long[] familyArray);
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 0bc4fdf..4c8b4f1 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -346,22 +346,24 @@
         private boolean mCanConstantState;
         private boolean mCheckedConstantState;
 
-        public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner,
+        public AnimatedRotateState(AnimatedRotateState orig, AnimatedRotateDrawable owner,
                 Resources res) {
-            if (source != null) {
+            if (orig != null) {
                 if (res != null) {
-                    mDrawable = source.mDrawable.getConstantState().newDrawable(res);
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                 } else {
-                    mDrawable = source.mDrawable.getConstantState().newDrawable();
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
                 }
                 mDrawable.setCallback(owner);
-                mDrawable.setLayoutDirection(source.mDrawable.getLayoutDirection());
-                mPivotXRel = source.mPivotXRel;
-                mPivotX = source.mPivotX;
-                mPivotYRel = source.mPivotYRel;
-                mPivotY = source.mPivotY;
-                mFramesCount = source.mFramesCount;
-                mFrameDuration = source.mFrameDuration;
+                mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
+                mDrawable.setBounds(orig.mDrawable.getBounds());
+                mDrawable.setLevel(orig.mDrawable.getLevel());
+                mPivotXRel = orig.mPivotXRel;
+                mPivotX = orig.mPivotX;
+                mPivotYRel = orig.mPivotYRel;
+                mPivotY = orig.mPivotY;
+                mFramesCount = orig.mFramesCount;
+                mFrameDuration = orig.mFrameDuration;
                 mCanConstantState = mCheckedConstantState = true;
             }
         }
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index f116376..61ef81b 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -285,6 +285,8 @@
                 }
                 mDrawable.setCallback(owner);
                 mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
+                mDrawable.setBounds(orig.mDrawable.getBounds());
+                mDrawable.setLevel(orig.mDrawable.getLevel());
                 mOrientation = orig.mOrientation;
                 mGravity = orig.mGravity;
                 mCheckedConstantState = mCanConstantState = true;
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index dd0f06f..a20b6d8 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -400,6 +400,8 @@
                 }
                 mDrawable.setCallback(owner);
                 mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
+                mDrawable.setBounds(orig.mDrawable.getBounds());
+                mDrawable.setLevel(orig.mDrawable.getLevel());
                 mInsetLeft = orig.mInsetLeft;
                 mInsetTop = orig.mInsetTop;
                 mInsetRight = orig.mInsetRight;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 43bc89a..001ed88 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -961,20 +961,22 @@
             // Default empty constructor.
         }
 
-        ChildDrawable(ChildDrawable or, LayerDrawable owner, Resources res) {
+        ChildDrawable(ChildDrawable orig, LayerDrawable owner, Resources res) {
             if (res != null) {
-                mDrawable = or.mDrawable.getConstantState().newDrawable(res);
+                mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
             } else {
-                mDrawable = or.mDrawable.getConstantState().newDrawable();
+                mDrawable = orig.mDrawable.getConstantState().newDrawable();
             }
             mDrawable.setCallback(owner);
-            mDrawable.setLayoutDirection(or.mDrawable.getLayoutDirection());
-            mThemeAttrs = or.mThemeAttrs;
-            mInsetL = or.mInsetL;
-            mInsetT = or.mInsetT;
-            mInsetR = or.mInsetR;
-            mInsetB = or.mInsetB;
-            mId = or.mId;
+            mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
+            mDrawable.setBounds(orig.mDrawable.getBounds());
+            mDrawable.setLevel(orig.mDrawable.getLevel());
+            mThemeAttrs = orig.mThemeAttrs;
+            mInsetL = orig.mInsetL;
+            mInsetT = orig.mInsetT;
+            mInsetR = orig.mInsetR;
+            mInsetB = orig.mInsetB;
+            mId = orig.mId;
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index ca32751f..7402bdb 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -33,7 +33,6 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.util.Log;
 
 import com.android.internal.R;
 
@@ -41,6 +40,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.Arrays;
 
 /**
  * Drawable that shows a ripple effect in response to state changes. The
@@ -88,7 +88,6 @@
  * @attr ref android.R.styleable#RippleDrawable_color
  */
 public class RippleDrawable extends LayerDrawable {
-    private static final String LOG_TAG = RippleDrawable.class.getSimpleName();
     private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
     private static final PorterDuffXfermode SRC_ATOP = new PorterDuffXfermode(Mode.SRC_ATOP);
     private static final PorterDuffXfermode SRC_OVER = new PorterDuffXfermode(Mode.SRC_OVER);
@@ -215,10 +214,14 @@
         final Ripple[] ripples = mAnimatingRipples;
         for (int i = 0; i < count; i++) {
             ripples[i].jump();
-            ripples[i] = null;
+        }
+        if (ripples != null) {
+            Arrays.fill(ripples, 0, count, null);
         }
         mAnimatingRipplesCount = 0;
         mClearingHotspots = false;
+
+        invalidateSelf();
     }
 
     @Override
@@ -549,6 +552,15 @@
         mAnimatingRipples[mAnimatingRipplesCount++] = mRipple;
     }
 
+    @Override
+    public void invalidateSelf() {
+        // Don't invalidate when we're clearing hotspots. We'll handle that
+        // manually when we're done.
+        if (!mClearingHotspots) {
+            super.invalidateSelf();
+        }
+    }
+
     private void removeRipple() {
         if (mRipple != null) {
             mRipple.exit();
@@ -572,7 +584,9 @@
         final Ripple[] ripples = mAnimatingRipples;
         for (int i = 0; i < count; i++) {
             ripples[i].cancel();
-            ripples[i] = null;
+        }
+        if (ripples != null) {
+            Arrays.fill(ripples, 0, count, null);
         }
         mAnimatingRipplesCount = 0;
         mClearingHotspots = false;
@@ -680,7 +694,7 @@
             final int count = mAnimatingRipplesCount;
             final int index = getRippleIndex(ripple);
             if (index >= 0) {
-                System.arraycopy(ripples, index + 1, ripples, index + 1 - 1, count - (index + 1));
+                System.arraycopy(ripples, index + 1, ripples, index, count - (index + 1));
                 ripples[count - 1] = null;
                 mAnimatingRipplesCount--;
                 invalidateSelf();
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 63b9e02..70482a6 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -507,21 +507,23 @@
         private boolean mCanConstantState;
         private boolean mCheckedConstantState;
 
-        public RotateState(RotateState source, RotateDrawable owner, Resources res) {
-            if (source != null) {
+        public RotateState(RotateState orig, RotateDrawable owner, Resources res) {
+            if (orig != null) {
                 if (res != null) {
-                    mDrawable = source.mDrawable.getConstantState().newDrawable(res);
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                 } else {
-                    mDrawable = source.mDrawable.getConstantState().newDrawable();
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
                 }
                 mDrawable.setCallback(owner);
-                mDrawable.setLayoutDirection(source.mDrawable.getLayoutDirection());
-                mPivotXRel = source.mPivotXRel;
-                mPivotX = source.mPivotX;
-                mPivotYRel = source.mPivotYRel;
-                mPivotY = source.mPivotY;
-                mFromDegrees = mCurrentDegrees = source.mFromDegrees;
-                mToDegrees = source.mToDegrees;
+                mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
+                mDrawable.setBounds(orig.mDrawable.getBounds());
+                mDrawable.setLevel(orig.mDrawable.getLevel());
+                mPivotXRel = orig.mPivotXRel;
+                mPivotX = orig.mPivotX;
+                mPivotYRel = orig.mPivotYRel;
+                mPivotY = orig.mPivotY;
+                mFromDegrees = mCurrentDegrees = orig.mFromDegrees;
+                mToDegrees = orig.mToDegrees;
                 mCanConstantState = mCheckedConstantState = true;
             }
         }
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index a954474..b40038a 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -295,6 +295,8 @@
                 }
                 mDrawable.setCallback(owner);
                 mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
+                mDrawable.setBounds(orig.mDrawable.getBounds());
+                mDrawable.setLevel(orig.mDrawable.getLevel());
                 mScaleWidth = orig.mScaleWidth;
                 mScaleHeight = orig.mScaleHeight;
                 mGravity = orig.mGravity;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 11568d2..c65efe4 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1557,7 +1557,7 @@
     };
     const char16_t* valueToString(const Res_value* value, size_t stringBlock,
                                   char16_t tmpBuffer[TMP_BUFFER_SIZE],
-                                  size_t* outLen);
+                                  size_t* outLen) const;
 
     struct bag_entry {
         ssize_t stringBlock;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3f014ef..690b1d6 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2939,7 +2939,7 @@
             for (size_t i = 0; i < bags->size(); i++) {
                 TABLE_NOISY(printf("type=%d\n", i));
                 const TypeList& typeList = types[i];
-                if (typeList.isEmpty()) {
+                if (!typeList.isEmpty()) {
                     bag_set** typeBags = bags->get(i);
                     TABLE_NOISY(printf("typeBags=%p\n", typeBags));
                     if (typeBags) {
@@ -3728,7 +3728,7 @@
 
 const char16_t* ResTable::valueToString(
     const Res_value* value, size_t stringBlock,
-    char16_t /*tmpBuffer*/ [TMP_BUFFER_SIZE], size_t* outLen)
+    char16_t /*tmpBuffer*/ [TMP_BUFFER_SIZE], size_t* outLen) const
 {
     if (!value) {
         return NULL;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index d9f7941..49560ff 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -12,6 +12,7 @@
 		font/CacheTexture.cpp \
 		font/Font.cpp \
 		AmbientShadow.cpp \
+		AnimationContext.cpp \
 		Animator.cpp \
 		AnimatorManager.cpp \
 		AssetAtlas.cpp \
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
new file mode 100644
index 0000000..d7d9743
--- /dev/null
+++ b/libs/hwui/AnimationContext.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+#include "AnimationContext.h"
+
+#include "Animator.h"
+#include "RenderNode.h"
+#include "TreeInfo.h"
+#include "renderthread/TimeLord.h"
+
+namespace android {
+namespace uirenderer {
+
+AnimationContext::AnimationContext(renderthread::TimeLord& clock)
+        : mClock(clock)
+        , mCurrentFrameAnimations(*this)
+        , mNextFrameAnimations(*this)
+        , mFrameTimeMs(0) {
+}
+
+AnimationContext::~AnimationContext() {
+    startFrame();
+    while (mCurrentFrameAnimations.mNextHandle) {
+        AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
+        AnimatorManager& animators = current->mRenderNode->animators();
+        animators.endAllAnimators();
+        LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
+                "endAllAnimators failed to remove from current frame list!");
+    }
+}
+
+void AnimationContext::addAnimatingRenderNode(RenderNode& node) {
+    if (!node.animators().hasAnimationHandle()) {
+        AnimationHandle* handle = new AnimationHandle(node, *this);
+        addAnimationHandle(handle);
+    }
+}
+
+void AnimationContext::addAnimationHandle(AnimationHandle* handle) {
+    handle->insertAfter(&mNextFrameAnimations);
+}
+
+void AnimationContext::startFrame() {
+    LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
+            "Missed running animations last frame!");
+    AnimationHandle* head = mNextFrameAnimations.mNextHandle;
+    if (head) {
+        mNextFrameAnimations.mNextHandle = NULL;
+        mCurrentFrameAnimations.mNextHandle = head;
+        head->mPreviousHandle = &mCurrentFrameAnimations;
+    }
+    mFrameTimeMs = mClock.computeFrameTimeMs();
+}
+
+void AnimationContext::runRemainingAnimations(TreeInfo& info) {
+    while (mCurrentFrameAnimations.mNextHandle) {
+        AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
+        AnimatorManager& animators = current->mRenderNode->animators();
+        animators.pushStaging();
+        animators.animateNoDamage(info);
+        LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
+                "Animate failed to remove from current frame list!");
+    }
+}
+
+void AnimationContext::callOnFinished(BaseRenderNodeAnimator* animator,
+        AnimationListener* listener) {
+    listener->onAnimationFinished(animator);
+}
+
+AnimationHandle::AnimationHandle(AnimationContext& context)
+        : mContext(context)
+        , mPreviousHandle(NULL)
+        , mNextHandle(NULL) {
+}
+
+AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& context)
+        : mRenderNode(&animatingNode)
+        , mContext(context)
+        , mPreviousHandle(NULL)
+        , mNextHandle(NULL) {
+    mRenderNode->animators().setAnimationHandle(this);
+}
+
+AnimationHandle::~AnimationHandle() {
+    LOG_ALWAYS_FATAL_IF(mPreviousHandle || mNextHandle,
+            "AnimationHandle destroyed while still animating!");
+}
+
+void AnimationHandle::notifyAnimationsRan() {
+    removeFromList();
+    if (mRenderNode->animators().hasAnimators()) {
+        mContext.addAnimationHandle(this);
+    } else {
+        release();
+    }
+}
+
+void AnimationHandle::release() {
+    LOG_ALWAYS_FATAL_IF(mRenderNode->animators().hasAnimators(),
+            "Releasing the handle for an RenderNode with outstanding animators!");
+    removeFromList();
+    mRenderNode->animators().setAnimationHandle(NULL);
+    delete this;
+}
+
+void AnimationHandle::insertAfter(AnimationHandle* prev) {
+    removeFromList();
+    mNextHandle = prev->mNextHandle;
+    if (mNextHandle) {
+        mNextHandle->mPreviousHandle = this;
+    }
+    prev->mNextHandle = this;
+    mPreviousHandle = prev;
+}
+
+void AnimationHandle::removeFromList() {
+    if (mPreviousHandle) {
+        mPreviousHandle->mNextHandle = mNextHandle;
+    }
+    if (mNextHandle) {
+        mNextHandle->mPreviousHandle = mPreviousHandle;
+    }
+    mPreviousHandle = NULL;
+    mNextHandle = NULL;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h
new file mode 100644
index 0000000..900d953
--- /dev/null
+++ b/libs/hwui/AnimationContext.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+#ifndef TREEANIMATIONTRACKER_H_
+#define TREEANIMATIONTRACKER_H_
+
+#include <cutils/compiler.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+#include "renderthread/TimeLord.h"
+#include "utils/Macros.h"
+
+namespace android {
+namespace uirenderer {
+
+class AnimationContext;
+class AnimationListener;
+class BaseRenderNodeAnimator;
+class RenderNode;
+class TreeInfo;
+
+/*
+ * AnimationHandle is several classes merged into one.
+ * 1: It maintains the reference to the AnimationContext required to run animators.
+ * 2: It keeps a strong reference to RenderNodes with animators so that
+ *    we don't lose them if they are no longer in the display tree. This is
+ *    required so that we can keep animating them, and properly notify listeners
+ *    of onAnimationFinished.
+ * 3: It forms a doubly linked list so that we can cheaply move between states.
+ */
+class AnimationHandle {
+    PREVENT_COPY_AND_ASSIGN(AnimationHandle);
+public:
+    AnimationContext& context() { return mContext; }
+
+    // Called by the RenderNode when it has internally pulsed its own animations
+    // this frame and does not need to be run again this frame.
+    void notifyAnimationsRan();
+
+    // Stops tracking the RenderNode and destroys the handle. The node must be
+    // re-attached to the AnimationContext to receive managed animation
+    // pulses.
+    void release();
+
+private:
+    friend class AnimationContext;
+    AnimationHandle(AnimationContext& context);
+    AnimationHandle(RenderNode& animatingNode, AnimationContext& context);
+    ~AnimationHandle();
+
+    void insertAfter(AnimationHandle* prev);
+    void removeFromList();
+
+    sp<RenderNode> mRenderNode;
+
+    AnimationContext& mContext;
+
+    AnimationHandle* mPreviousHandle;
+    AnimationHandle* mNextHandle;
+};
+
+class AnimationContext {
+    PREVENT_COPY_AND_ASSIGN(AnimationContext);
+public:
+    ANDROID_API AnimationContext(renderthread::TimeLord& clock);
+    ANDROID_API virtual ~AnimationContext();
+
+    nsecs_t frameTimeMs() { return mFrameTimeMs; }
+    bool hasAnimations() {
+        return mCurrentFrameAnimations.mNextHandle
+                || mNextFrameAnimations.mNextHandle;
+    }
+
+    // Will always add to the next frame list, which is swapped when
+    // startFrame() is called
+    ANDROID_API void addAnimatingRenderNode(RenderNode& node);
+
+    // Marks the start of a frame, which will update the frame time and move all
+    // next frame animations into the current frame
+    ANDROID_API virtual void startFrame();
+
+    // Runs any animations still left in mCurrentFrameAnimations that were not run
+    // as part of the standard RenderNode:prepareTree pass.
+    ANDROID_API virtual void runRemainingAnimations(TreeInfo& info);
+
+    ANDROID_API virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener);
+
+private:
+    friend class AnimationHandle;
+    void addAnimationHandle(AnimationHandle* handle);
+
+    renderthread::TimeLord& mClock;
+
+    // Animations left to run this frame, at the end of the frame this should
+    // be null
+    AnimationHandle mCurrentFrameAnimations;
+    // Animations queued for next frame
+    AnimationHandle mNextFrameAnimations;
+
+    nsecs_t mFrameTimeMs;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TREEANIMATIONTRACKER_H_ */
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 78d569d..da65f38 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -19,6 +19,7 @@
 #include <inttypes.h>
 #include <set>
 
+#include "AnimationContext.h"
 #include "RenderNode.h"
 #include "RenderProperties.h"
 
@@ -85,7 +86,7 @@
     onAttached();
 }
 
-void BaseRenderNodeAnimator::pushStaging(TreeInfo& info) {
+void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
     if (!mHasStartValue) {
         doSetStartValue(getValue(mTarget));
     }
@@ -93,21 +94,24 @@
         mPlayState = mStagingPlayState;
         // Oh boy, we're starting! Man the battle stations!
         if (mPlayState == RUNNING) {
-            transitionToRunning(info);
+            transitionToRunning(context);
+        } else if (mPlayState == FINISHED) {
+            callOnFinishedListener(context);
         }
     }
 }
 
-void BaseRenderNodeAnimator::transitionToRunning(TreeInfo& info) {
-    LOG_ALWAYS_FATAL_IF(info.frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", info.frameTimeMs);
+void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
+    nsecs_t frameTimeMs = context.frameTimeMs();
+    LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs);
     if (mStartDelay < 0 || mStartDelay > 50000) {
         ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
     }
-    mStartTime = info.frameTimeMs + mStartDelay;
+    mStartTime = frameTimeMs + mStartDelay;
     if (mStartTime < 0) {
         ALOGW("Ended up with a really weird start time of %" PRId64
                 " with frame time %" PRId64 " and start delay %" PRId64,
-                mStartTime, info.frameTimeMs, mStartDelay);
+                mStartTime, frameTimeMs, mStartDelay);
         // Set to 0 so that the animate() basically instantly finishes
         mStartTime = 0;
     }
@@ -120,7 +124,7 @@
     }
 }
 
-bool BaseRenderNodeAnimator::animate(TreeInfo& info) {
+bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
     if (mPlayState < RUNNING) {
         return false;
     }
@@ -132,15 +136,14 @@
     // because the staging properties reflect the final value, we always need
     // to call setValue even if the animation isn't yet running or is still
     // being delayed as we need to override the staging value
-    if (mStartTime > info.frameTimeMs) {
-        info.out.hasAnimations |= true;
+    if (mStartTime > context.frameTimeMs()) {
         setValue(mTarget, mFromValue);
         return false;
     }
 
     float fraction = 1.0f;
     if (mPlayState == RUNNING && mDuration > 0) {
-        fraction = (float)(info.frameTimeMs - mStartTime) / mDuration;
+        fraction = (float)(context.frameTimeMs() - mStartTime) / mDuration;
     }
     if (fraction >= 1.0f) {
         fraction = 1.0f;
@@ -151,21 +154,16 @@
     setValue(mTarget, mFromValue + (mDeltaValue * fraction));
 
     if (mPlayState == FINISHED) {
-        callOnFinishedListener(info);
+        callOnFinishedListener(context);
         return true;
     }
 
-    info.out.hasAnimations |= true;
     return false;
 }
 
-void BaseRenderNodeAnimator::callOnFinishedListener(TreeInfo& info) {
+void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
     if (mListener.get()) {
-        if (!info.animationHook) {
-            mListener->onAnimationFinished(this);
-        } else {
-            info.animationHook->callOnFinished(this, mListener.get());
-        }
+        context.callOnFinished(this, mListener.get());
     }
 }
 
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 6dfe7b4..c52a93f 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -28,6 +28,8 @@
 namespace android {
 namespace uirenderer {
 
+class AnimationContext;
+class BaseRenderNodeAnimator;
 class RenderNode;
 class RenderProperties;
 
@@ -50,15 +52,17 @@
     ANDROID_API void setListener(AnimationListener* listener) {
         mListener = listener;
     }
+    AnimationListener* listener() { return mListener.get(); }
     ANDROID_API void start() { mStagingPlayState = RUNNING; onStagingPlayStateChanged(); }
     ANDROID_API void end() { mStagingPlayState = FINISHED; onStagingPlayStateChanged(); }
 
     void attach(RenderNode* target);
     virtual void onAttached() {}
     void detach() { mTarget = 0; }
-    void pushStaging(TreeInfo& info);
-    bool animate(TreeInfo& info);
+    void pushStaging(AnimationContext& context);
+    bool animate(AnimationContext& context);
 
+    bool isRunning() { return mPlayState == RUNNING; }
     bool isFinished() { return mPlayState == FINISHED; }
     float finalValue() { return mFinalValue; }
 
@@ -72,7 +76,7 @@
     virtual void setValue(RenderNode* target, float value) = 0;
     RenderNode* target() { return mTarget; }
 
-    void callOnFinishedListener(TreeInfo& info);
+    void callOnFinishedListener(AnimationContext& context);
 
     virtual void onStagingPlayStateChanged() {}
 
@@ -100,7 +104,7 @@
 
 private:
     inline void checkMutable();
-    virtual void transitionToRunning(TreeInfo& info);
+    virtual void transitionToRunning(AnimationContext& context);
     void doSetStartValue(float value);
 };
 
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 7221295a4..678b1ee 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -17,6 +17,7 @@
 
 #include <algorithm>
 
+#include "AnimationContext.h"
 #include "RenderNode.h"
 
 namespace android {
@@ -30,7 +31,8 @@
 }
 
 AnimatorManager::AnimatorManager(RenderNode& parent)
-        : mParent(parent) {
+        : mParent(parent)
+        , mAnimationHandle(NULL) {
 }
 
 AnimatorManager::~AnimatorManager() {
@@ -44,6 +46,11 @@
     mNewAnimators.push_back(animator.get());
 }
 
+void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
+    LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
+    mAnimationHandle = handle;
+}
+
 template<typename T>
 static void move_all(T& source, T& dest) {
     dest.reserve(source.size() + dest.size());
@@ -53,26 +60,30 @@
     source.clear();
 }
 
-void AnimatorManager::pushStaging(TreeInfo& info) {
+void AnimatorManager::pushStaging() {
     if (mNewAnimators.size()) {
         // Since this is a straight move, we don't need to inc/dec the ref count
         move_all(mNewAnimators, mAnimators);
     }
     for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
-        (*it)->pushStaging(info);
+        (*it)->pushStaging(mAnimationHandle->context());
     }
 }
 
 class AnimateFunctor {
 public:
-    AnimateFunctor(RenderNode& target, TreeInfo& info)
-            : dirtyMask(0), mTarget(target), mInfo(info) {}
+    AnimateFunctor(TreeInfo& info, AnimationContext& context)
+            : dirtyMask(0), mInfo(info), mContext(context) {}
 
     bool operator() (BaseRenderNodeAnimator* animator) {
         dirtyMask |= animator->dirtyMask();
-        bool remove = animator->animate(mInfo);
+        bool remove = animator->animate(mContext);
         if (remove) {
             animator->decStrong(0);
+        } else {
+            if (animator->isRunning()) {
+                mInfo.out.hasAnimations = true;
+            }
         }
         return remove;
     }
@@ -80,8 +91,8 @@
     uint32_t dirtyMask;
 
 private:
-    RenderNode& mTarget;
     TreeInfo& mInfo;
+    AnimationContext& mContext;
 };
 
 uint32_t AnimatorManager::animate(TreeInfo& info) {
@@ -93,17 +104,72 @@
     mParent.damageSelf(info);
     info.damageAccumulator->popTransform();
 
-    AnimateFunctor functor(mParent, info);
-    std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
-    newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
-    mAnimators.erase(newEnd, mAnimators.end());
+    uint32_t dirty = animateCommon(info);
 
     mParent.mProperties.updateMatrix();
     info.damageAccumulator->pushTransform(&mParent);
     mParent.damageSelf(info);
 
+    return dirty;
+}
+
+void AnimatorManager::animateNoDamage(TreeInfo& info) {
+    if (!mAnimators.size()) return;
+
+    animateCommon(info);
+}
+
+uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
+    AnimateFunctor functor(info, mAnimationHandle->context());
+    std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
+    newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
+    mAnimators.erase(newEnd, mAnimators.end());
+    mAnimationHandle->notifyAnimationsRan();
     return functor.dirtyMask;
 }
 
+class EndAnimatorsFunctor {
+public:
+    EndAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
+
+    void operator() (BaseRenderNodeAnimator* animator) {
+        animator->end();
+        animator->pushStaging(mContext);
+        animator->animate(mContext);
+        animator->decStrong(0);
+    }
+
+private:
+    AnimationContext& mContext;
+};
+
+static void endAnimatorsHard(BaseRenderNodeAnimator* animator) {
+    animator->end();
+    if (animator->listener()) {
+        animator->listener()->onAnimationFinished(animator);
+    }
+    animator->decStrong(0);
+}
+
+void AnimatorManager::endAllAnimators() {
+    if (mNewAnimators.size()) {
+        // Since this is a straight move, we don't need to inc/dec the ref count
+        move_all(mNewAnimators, mAnimators);
+    }
+    // First try gracefully ending them
+    if (mAnimationHandle) {
+        EndAnimatorsFunctor functor(mAnimationHandle->context());
+        for_each(mAnimators.begin(), mAnimators.end(), functor);
+        mAnimators.clear();
+        mAnimationHandle->release();
+    } else {
+        // We have no context, so bust out the sledgehammer
+        // This works because this state can only happen on the UI thread,
+        // which means we're already on the right thread to invoke listeners
+        for_each(mAnimators.begin(), mAnimators.end(), endAnimatorsHard);
+        mAnimators.clear();
+    }
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index 0d177c5..d5f56ed 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -27,6 +27,7 @@
 namespace android {
 namespace uirenderer {
 
+class AnimationHandle;
 class BaseRenderNodeAnimator;
 class RenderNode;
 
@@ -39,12 +40,26 @@
 
     void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
 
-    void pushStaging(TreeInfo& info);
+    void setAnimationHandle(AnimationHandle* handle);
+    bool hasAnimationHandle() { return mAnimationHandle; }
+
+    void pushStaging();
+
     // Returns the combined dirty mask of all animators run
     uint32_t animate(TreeInfo& info);
 
+    void animateNoDamage(TreeInfo& info);
+
+    // Hard-ends all animators. Used for cleanup if the root is being destroyed.
+    ANDROID_API void endAllAnimators();
+
+    bool hasAnimators() { return mAnimators.size(); }
+
 private:
+    uint32_t animateCommon(TreeInfo& info);
+
     RenderNode& mParent;
+    AnimationHandle* mAnimationHandle;
 
     // To improve the efficiency of resizing & removing from the vector
     // use manual ref counting instead of sp<>.
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 8818510..5ff7b7f 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1528,8 +1528,7 @@
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
         TessellationCache::vertexBuffer_pair_t buffers;
-        Matrix4 drawTransform;
-        renderer.getMatrix(&drawTransform);
+        Matrix4 drawTransform(*(renderer.currentTransform()));
         renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
                 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
                 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
diff --git a/libs/hwui/IContextFactory.h b/libs/hwui/IContextFactory.h
new file mode 100644
index 0000000..463b55e
--- /dev/null
+++ b/libs/hwui/IContextFactory.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#ifndef CONTEXTFACTORY_H_
+#define CONTEXTFACTORY_H_
+
+namespace android {
+namespace uirenderer {
+
+namespace renderthread {
+class TimeLord;
+}
+
+class AnimationContext;
+
+class IContextFactory {
+public:
+    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) = 0;
+
+protected:
+    virtual ~IContextFactory() {}
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* CONTEXTFACTORY_H_ */
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 658265d..6a92a6e 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -34,6 +34,7 @@
 #include "LayerRenderer.h"
 #include "OpenGLRenderer.h"
 #include "utils/MathUtils.h"
+#include "renderthread/CanvasContext.h"
 
 namespace android {
 namespace uirenderer {
@@ -208,6 +209,13 @@
     if (info.renderer && mLayer->deferredUpdateScheduled) {
         info.renderer->pushLayerUpdate(mLayer);
     }
+
+    if (CC_UNLIKELY(info.canvasContext)) {
+        // If canvasContext is not null that means there are prefetched layers
+        // that need to be accounted for. That might be us, so tell CanvasContext
+        // that this layer is in the tree and should not be destroyed.
+        info.canvasContext->markLayerInUse(this);
+    }
 }
 
 void RenderNode::prepareTreeImpl(TreeInfo& info) {
@@ -235,7 +243,7 @@
     // before properties() is trampled by stagingProperties(), as they are
     // required by some animators.
     if (CC_LIKELY(info.runAnimations)) {
-        mAnimatorManager.pushStaging(info);
+        mAnimatorManager.pushStaging();
     }
     if (mDirtyPropertyFields) {
         mDirtyPropertyFields = 0;
@@ -653,41 +661,12 @@
     handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
 }
 
-template <class T>
-int RenderNode::issueOperationsOfNegZChildren(
-        const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-        OpenGLRenderer& renderer, T& handler) {
-    if (zTranslatedNodes.isEmpty()) return -1;
-
-    // create a save around the body of the ViewGroup's draw method, so that
-    // matrix/clip methods don't affect composited children
-    int shadowSaveCount = renderer.getSaveCount();
-    handler(new (handler.allocator()) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
-            PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
-    issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
-    return shadowSaveCount;
-}
-
-template <class T>
-void RenderNode::issueOperationsOfPosZChildren(int shadowRestoreTo,
-        const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-        OpenGLRenderer& renderer, T& handler) {
-    if (zTranslatedNodes.isEmpty()) return;
-
-    LOG_ALWAYS_FATAL_IF(shadowRestoreTo < 0, "invalid save to restore to");
-    handler(new (handler.allocator()) RestoreToCountOp(shadowRestoreTo),
-            PROPERTY_SAVECOUNT, properties().getClipToBounds());
-    renderer.setOverrideLayerAlpha(1.0f);
-
-    issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
-}
-
 #define SHADOW_DELTA 0.1f
 
 template <class T>
-void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-        ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) {
+void RenderNode::issueOperationsOf3dChildren(ChildrenSelectMode mode,
+        const Matrix4& initialTransform, const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
+        OpenGLRenderer& renderer, T& handler) {
     const int size = zTranslatedNodes.size();
     if (size == 0
             || (mode == kNegativeZChildren && zTranslatedNodes[0].key > 0.0f)
@@ -696,6 +675,11 @@
         return;
     }
 
+    // Apply the base transform of the parent of the 3d children. This isolates
+    // 3d children of the current chunk from transformations made in previous chunks.
+    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
+    renderer.setMatrix(initialTransform);
+
     /**
      * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
      * with very similar Z heights to draw together.
@@ -750,6 +734,7 @@
         renderer.restoreToCount(restoreTo);
         drawIndex++;
     }
+    renderer.restoreToCount(rootRestoreTo);
 }
 
 template <class T>
@@ -869,6 +854,8 @@
     bool quickRejected = properties().getClipToBounds()
             && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
     if (!quickRejected) {
+        Matrix4 initialTransform(*(renderer.currentTransform()));
+
         if (drawLayer) {
             handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
@@ -880,9 +867,9 @@
                 Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
                 buildZSortedChildList(chunk, zTranslatedNodes);
 
-                // for 3d root, draw children with negative z values
-                int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes,
-                        renderer, handler);
+                issueOperationsOf3dChildren(kNegativeZChildren,
+                        initialTransform, zTranslatedNodes, renderer, handler);
+
                 const int saveCountOffset = renderer.getSaveCount() - 1;
                 const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
 
@@ -899,8 +886,8 @@
                     }
                 }
 
-                // for 3d root, draw children with positive z values
-                issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+                issueOperationsOf3dChildren(kPositiveZChildren,
+                        initialTransform, zTranslatedNodes, renderer, handler);
             }
         }
     }
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 18402b2..d897997 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -174,6 +174,8 @@
     // UI thread only!
     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
 
+    AnimatorManager& animators() { return mAnimatorManager; }
+
     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
 
 private:
@@ -206,16 +208,9 @@
     inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
 
     template <class T>
-    inline int issueOperationsOfNegZChildren(
-            const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
+    inline void issueOperationsOf3dChildren(ChildrenSelectMode mode,
+            const Matrix4& initialTransform, const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
             OpenGLRenderer& renderer, T& handler);
-    template <class T>
-    inline void issueOperationsOfPosZChildren(int shadowRestoreTo,
-            const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-            OpenGLRenderer& renderer, T& handler);
-    template <class T>
-    inline void issueOperationsOf3dChildren(const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-            ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);
 
     template <class T>
     inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index bdac47b..3e1aed3 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -102,10 +102,6 @@
 // Matrix
 ///////////////////////////////////////////////////////////////////////////////
 
-void StatefulBaseRenderer::getMatrix(Matrix4* matrix) const {
-    matrix->load(*(mSnapshot->transform));
-}
-
 void StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const {
     mSnapshot->transform->copyTo(*matrix);
 }
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index 3957d36..c6974b4 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -69,7 +69,6 @@
     //        int alpha, SkXfermode::Mode mode, int flags);
 
     // Matrix
-    void getMatrix(Matrix4* outMatrix) const;
     virtual void getMatrix(SkMatrix* outMatrix) const;
     virtual void translate(float dx, float dy, float dz = 0.0f);
     virtual void rotate(float degrees);
@@ -100,6 +99,10 @@
     void setClippingRoundRect(LinearAllocator& allocator,
             const Rect& rect, float radius);
 
+    inline const mat4* currentTransform() const {
+        return mSnapshot->transform;
+    }
+
 protected:
     const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
 
@@ -134,10 +137,6 @@
         return mSnapshot->clipRect;
     }
 
-    inline const mat4* currentTransform() const {
-        return mSnapshot->transform;
-    }
-
     inline const Snapshot* currentSnapshot() const {
         return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get();
     }
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 74d52a3..ae6ea94 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -26,18 +26,13 @@
 namespace android {
 namespace uirenderer {
 
-class BaseRenderNodeAnimator;
-class AnimationListener;
+namespace renderthread {
+class CanvasContext;
+}
+
 class OpenGLRenderer;
 class RenderState;
 
-class AnimationHook {
-public:
-    virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) = 0;
-protected:
-    ~AnimationHook() {}
-};
-
 class ErrorHandler {
 public:
     virtual void onError(const std::string& message) = 0;
@@ -62,31 +57,27 @@
 
     explicit TreeInfo(TraversalMode mode, RenderState& renderState)
         : mode(mode)
-        , frameTimeMs(0)
-        , animationHook(NULL)
         , prepareTextures(mode == MODE_FULL)
         , runAnimations(true)
         , damageAccumulator(NULL)
         , renderState(renderState)
         , renderer(NULL)
         , errorHandler(NULL)
+        , canvasContext(NULL)
     {}
 
     explicit TreeInfo(TraversalMode mode, const TreeInfo& clone)
         : mode(mode)
-        , frameTimeMs(clone.frameTimeMs)
-        , animationHook(clone.animationHook)
         , prepareTextures(mode == MODE_FULL)
         , runAnimations(clone.runAnimations)
         , damageAccumulator(clone.damageAccumulator)
         , renderState(clone.renderState)
         , renderer(clone.renderer)
         , errorHandler(clone.errorHandler)
+        , canvasContext(clone.canvasContext)
     {}
 
     const TraversalMode mode;
-    nsecs_t frameTimeMs;
-    AnimationHook* animationHook;
     // TODO: Remove this? Currently this is used to signal to stop preparing
     // textures if we run out of cache space.
     bool prepareTextures;
@@ -104,6 +95,8 @@
     // layer updates or similar. May be NULL.
     OpenGLRenderer* renderer;
     ErrorHandler* errorHandler;
+    // TODO: Remove this? May be NULL
+    renderthread::CanvasContext* canvasContext;
 
     struct Out {
         Out()
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4bf5a8a..491a295 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -16,11 +16,13 @@
 
 #include "CanvasContext.h"
 
+#include <algorithm>
 #include <private/hwui/DrawGlInfo.h>
 #include <strings.h>
 
 #include "EglManager.h"
 #include "RenderThread.h"
+#include "../AnimationContext.h"
 #include "../Caches.h"
 #include "../DeferredLayerUpdater.h"
 #include "../RenderState.h"
@@ -35,7 +37,8 @@
 namespace uirenderer {
 namespace renderthread {
 
-CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode)
+CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
+        RenderNode* rootRenderNode, IContextFactory* contextFactory)
         : mRenderThread(thread)
         , mEglManager(thread.eglManager())
         , mEglSurface(EGL_NO_SURFACE)
@@ -44,11 +47,14 @@
         , mCanvas(NULL)
         , mHaveNewSurface(false)
         , mRootRenderNode(rootRenderNode) {
+    mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord());
 }
 
 CanvasContext::~CanvasContext() {
     destroyCanvasAndSurface();
     mRenderThread.removeFrameCallback(this);
+    delete mAnimationContext;
+    freePrefetechedLayers();
 }
 
 void CanvasContext::destroyCanvasAndSurface() {
@@ -136,10 +142,18 @@
 void CanvasContext::prepareTree(TreeInfo& info) {
     mRenderThread.removeFrameCallback(this);
 
-    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
     info.damageAccumulator = &mDamageAccumulator;
     info.renderer = mCanvas;
+    if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
+        info.canvasContext = this;
+    }
+    mAnimationContext->startFrame();
     mRootRenderNode->prepareTree(info);
+    mAnimationContext->runRemainingAnimations(info);
+
+    if (info.canvasContext) {
+        freePrefetechedLayers();
+    }
 
     int runningBehind = 0;
     // TODO: This query is moderately expensive, investigate adding some sort
@@ -244,6 +258,26 @@
     thread.renderState().invokeFunctor(functor, mode, NULL);
 }
 
+void CanvasContext::markLayerInUse(RenderNode* node) {
+    if (mPrefetechedLayers.erase(node)) {
+        node->decStrong(0);
+    }
+}
+
+static void destroyPrefetechedNode(RenderNode* node) {
+    ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName());
+    node->destroyHardwareResources();
+    node->decStrong(0);
+}
+
+void CanvasContext::freePrefetechedLayers() {
+    if (mPrefetechedLayers.size()) {
+        requireGlContext();
+        std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode);
+        mPrefetechedLayers.clear();
+    }
+}
+
 void CanvasContext::buildLayer(RenderNode* node) {
     ATRACE_CALL();
     if (!mEglManager.hasEglContext() || !mCanvas) {
@@ -254,7 +288,6 @@
     stopDrawing();
 
     TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
-    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
     info.damageAccumulator = &mDamageAccumulator;
     info.renderer = mCanvas;
     info.runAnimations = false;
@@ -266,6 +299,9 @@
     node->setPropertyFieldsDirty(RenderNode::GENERIC);
 
     mCanvas->flushLayerUpdates();
+
+    node->incStrong(0);
+    mPrefetechedLayers.insert(node);
 }
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
@@ -278,6 +314,7 @@
     stopDrawing();
     if (mEglManager.hasEglContext()) {
         requireGlContext();
+        freePrefetechedLayers();
         mRootRenderNode->destroyHardwareResources();
         Caches::getInstance().flush(Caches::kFlushMode_Layers);
     }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0cbed6f..7c27190 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,6 +17,8 @@
 #ifndef CANVASCONTEXT_H_
 #define CANVASCONTEXT_H_
 
+#include <set>
+
 #include <cutils/compiler.h>
 #include <EGL/egl.h>
 #include <SkBitmap.h>
@@ -25,6 +27,7 @@
 
 #include "../DamageAccumulator.h"
 #include "../DrawProfiler.h"
+#include "../IContextFactory.h"
 #include "../RenderNode.h"
 #include "RenderTask.h"
 #include "RenderThread.h"
@@ -34,6 +37,7 @@
 namespace android {
 namespace uirenderer {
 
+class AnimationContext;
 class DeferredLayerUpdater;
 class OpenGLRenderer;
 class Rect;
@@ -45,9 +49,11 @@
 
 // This per-renderer class manages the bridge between the global EGL context
 // and the render surface.
+// TODO: Rename to Renderer or some other per-window, top-level manager
 class CanvasContext : public IFrameCallback {
 public:
-    CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode);
+    CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+            IContextFactory* contextFactory);
     virtual ~CanvasContext();
 
     bool initialize(ANativeWindow* window);
@@ -67,6 +73,7 @@
 
     void buildLayer(RenderNode* node);
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
+    void markLayerInUse(RenderNode* node);
 
     void destroyHardwareResources();
     static void trimMemory(RenderThread& thread, int level);
@@ -95,6 +102,8 @@
 
     void requireGlContext();
 
+    void freePrefetechedLayers();
+
     RenderThread& mRenderThread;
     EglManager& mEglManager;
     sp<ANativeWindow> mNativeWindow;
@@ -105,10 +114,13 @@
     OpenGLRenderer* mCanvas;
     bool mHaveNewSurface;
     DamageAccumulator mDamageAccumulator;
+    AnimationContext* mAnimationContext;
 
     const sp<RenderNode> mRootRenderNode;
 
     DrawProfiler mProfiler;
+
+    std::set<RenderNode*> mPrefetechedLayers;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 37f8e60..e030cdb 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "EglContext"
-
 #include "EglManager.h"
 
 #include <cutils/log.h>
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 405ce24..3d04316 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -52,17 +52,20 @@
     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
     ARGS(method) *args = (ARGS(method) *) task->payload()
 
-CREATE_BRIDGE3(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode) {
-    return new CanvasContext(*args->thread, args->translucent, args->rootRenderNode);
+CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
+        RenderNode* rootRenderNode, IContextFactory* contextFactory) {
+    return new CanvasContext(*args->thread, args->translucent,
+            args->rootRenderNode, args->contextFactory);
 }
 
-RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode)
+RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
         : mRenderThread(RenderThread::getInstance())
         , mContext(0) {
     SETUP_TASK(createContext);
     args->translucent = translucent;
     args->rootRenderNode = rootRenderNode;
     args->thread = &mRenderThread;
+    args->contextFactory = contextFactory;
     mContext = (CanvasContext*) postAndWait(task);
     mDrawFrameTask.setContext(&mRenderThread, mContext);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index eea3674..9e6bcf5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -30,6 +30,7 @@
 #include <utils/Vector.h>
 
 #include "../Caches.h"
+#include "../IContextFactory.h"
 #include "DrawFrameTask.h"
 
 namespace android {
@@ -58,7 +59,7 @@
  */
 class ANDROID_API RenderProxy {
 public:
-    ANDROID_API RenderProxy(bool translucent, RenderNode* rootNode);
+    ANDROID_API RenderProxy(bool translucent, RenderNode* rootNode, IContextFactory* contextFactory);
     ANDROID_API virtual ~RenderProxy();
 
     ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos);
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index 758d96e..cf3d039 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -30,7 +30,7 @@
     }
 }
 
-nsecs_t TimeLord::frameTimeMs() {
+nsecs_t TimeLord::computeFrameTimeMs() {
     // Logic copied from Choreographer.java
     nsecs_t now = systemTime(CLOCK_MONOTONIC);
     nsecs_t jitterNanos = now - mFrameTimeNanos;
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 52c6d9ef..8b0372c 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -30,7 +30,7 @@
 public:
     void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
     void vsyncReceived(nsecs_t vsync);
-    nsecs_t frameTimeMs();
+    nsecs_t computeFrameTimeMs();
 
 private:
     friend class RenderThread;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e69c456..e2770b4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1688,11 +1688,19 @@
 
     /**
      * Return a new audio session identifier not associated with any player or effect.
-     * It can for instance be used to create one of the {@link android.media.audiofx.AudioEffect}
-     * objects or specify a session for speech synthesis in
-     * {@link android.speech.tts.TextToSpeech.Engine}.
+     * An audio session identifier is a system wide unique identifier for a set of audio streams
+     * (one or more mixed together).
+     * <p>The primary use of the audio session ID is to associate audio effects to audio players,
+     * such as {@link MediaPlayer} or {@link AudioTrack}: all audio effects sharing the same audio
+     * session ID will be applied to the mixed audio content of the players that share the same
+     * audio session.
+     * <p>This method can for instance be used when creating one of the
+     * {@link android.media.audiofx.AudioEffect} objects to define the audio session of the effect,
+     * or to specify a session for a speech synthesis utterance
+     * in {@link android.speech.tts.TextToSpeech.Engine}.
      * @return a new unclaimed and unused audio session identifier, or {@link #ERROR} when the
-     *   system failed to generate a new session.
+     *   system failed to generate a new session, a condition in which audio playback or recording
+     *   will subsequently fail as well.
      */
     public int generateAudioSessionId() {
         int session = AudioSystem.newAudioSessionId();
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index dae539b..d002924 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -200,6 +200,7 @@
     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
     private static final int MSG_SYSTEM_READY = 21;
     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
+    private static final int MSG_PERSIST_MICROPHONE_MUTE = 23;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -873,6 +874,10 @@
         AudioSystem.setMasterMute(masterMute);
         broadcastMasterMuteStatus(masterMute);
 
+        boolean microphoneMute =
+                System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1;
+        AudioSystem.muteMicrophone(microphoneMute);
+
         // Each stream will read its own persisted settings
 
         // Broadcast the sticky intent
@@ -1447,17 +1452,15 @@
         if (mUseFixedVolume) {
             return;
         }
-
         if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(),
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return;
         }
-
         if (state != AudioSystem.getMasterMute()) {
             AudioSystem.setMasterMute(state);
             // Post a persist master volume msg
             sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
-                    : 0, 0, null, PERSIST_DELAY);
+                    : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
             sendMasterMuteUpdate(state, flags);
         }
     }
@@ -1563,6 +1566,9 @@
         }
 
         AudioSystem.muteMicrophone(on);
+        // Post a persist microphone msg.
+        sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
+                : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
     }
 
     /** @see AudioManager#getRingerMode() */
@@ -3486,13 +3492,28 @@
         private void dump(PrintWriter pw) {
             pw.print("   Mute count: ");
             pw.println(muteCount());
+            pw.print("   Max: ");
+            pw.println((mIndexMax + 5) / 10);
             pw.print("   Current: ");
             Set set = mIndex.entrySet();
             Iterator i = set.iterator();
             while (i.hasNext()) {
                 Map.Entry entry = (Map.Entry)i.next();
-                pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue())
-                             + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", ");
+                final int device = (Integer) entry.getKey();
+                pw.print(Integer.toHexString(device));
+                final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
+                        : AudioSystem.getOutputDeviceName(device);
+                if (!deviceName.isEmpty()) {
+                    pw.print(" (");
+                    pw.print(deviceName);
+                    pw.print(")");
+                }
+                pw.print(": ");
+                final int index = (((Integer) entry.getValue()) + 5) / 10;
+                pw.print(index);
+                if (i.hasNext()) {
+                    pw.print(", ");
+                }
             }
         }
     }
@@ -3819,7 +3840,6 @@
 
         @Override
         public void handleMessage(Message msg) {
-
             switch (msg.what) {
 
                 case MSG_SET_DEVICE_VOLUME:
@@ -3851,7 +3871,7 @@
                     Settings.System.putIntForUser(mContentResolver,
                                                  Settings.System.VOLUME_MASTER_MUTE,
                                                  msg.arg1,
-                                                 UserHandle.USER_CURRENT);
+                                                 msg.arg2);
                     break;
 
                 case MSG_PERSIST_RINGER_MODE:
@@ -4046,6 +4066,12 @@
                             Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
                             UserHandle.USER_CURRENT);
                     break;
+                case MSG_PERSIST_MICROPHONE_MUTE:
+                    Settings.System.putIntForUser(mContentResolver,
+                                                 Settings.System.MICROPHONE_MUTE,
+                                                 msg.arg1,
+                                                 msg.arg2);
+                    break;
             }
         }
     }
@@ -4290,7 +4316,8 @@
         if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
             int devices = 0;
             for (int dev : mConnectedDevices.keySet()) {
-                if ((dev & mBecomingNoisyIntentDevices) != 0) {
+                if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) &&
+                        ((dev & mBecomingNoisyIntentDevices) != 0)) {
                    devices |= dev;
                 }
             }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e11aab1..9a76f94 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -371,6 +371,7 @@
     public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
     public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
     public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
+    public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line";
 
     public static String getOutputDeviceName(int device)
     {
@@ -417,6 +418,8 @@
             return DEVICE_OUT_SPDIF_NAME;
         case DEVICE_OUT_FM:
             return DEVICE_OUT_FM_NAME;
+        case DEVICE_OUT_AUX_LINE:
+            return DEVICE_OUT_AUX_LINE_NAME;
         case DEVICE_OUT_DEFAULT:
         default:
             return "";
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 2856edb..522e45d 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -123,7 +123,7 @@
      */
     public abstract long getTimestamp();
 
-    protected Rect mCropRect;
+    private Rect mCropRect;
 
     /**
      * Get the crop rectangle associated with this frame.
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 96e6ab9..032f07f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -665,7 +665,7 @@
      * Thrown when an internal codec error occurs.
      */
     public final static class CodecException extends IllegalStateException {
-        public CodecException(int errorCode, int actionCode, String detailMessage) {
+        CodecException(int errorCode, int actionCode, String detailMessage) {
             super(detailMessage);
             mErrorCode = errorCode;
             mActionCode = actionCode;
@@ -1729,7 +1729,7 @@
             if (cropRect != null) {
                 cropRect.offset(-xOffset, -yOffset);
             }
-            mCropRect = cropRect;
+            setCropRect(cropRect);
 
             // save offsets and info
             mXOffset = xOffset;
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index acb2186..323a3e3 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -70,7 +70,7 @@
         mIsEncoder = isEncoder;
         mCaps = new HashMap<String, CodecCapabilities>();
         for (CodecCapabilities c: caps) {
-            mCaps.put(c.getMime(), c);
+            mCaps.put(c.getMimeType(), c);
         }
     }
 
@@ -98,6 +98,43 @@
         return types;
     }
 
+    private static int checkPowerOfTwo(int value, String message) {
+        if ((value & (value - 1)) != 0) {
+            throw new IllegalArgumentException(message);
+        }
+        return value;
+    }
+
+    private static class Feature {
+        public String mName;
+        public int mValue;
+        public boolean mDefault;
+        public Feature(String name, int value, boolean def) {
+            mName = name;
+            mValue = value;
+            mDefault = def;
+        }
+    }
+
+    // COMMON CONSTANTS
+    private static final Range<Integer> POSITIVE_INTEGERS =
+        Range.create(1, Integer.MAX_VALUE);
+    private static final Range<Long> POSITIVE_LONGS =
+        Range.create(1l, Long.MAX_VALUE);
+    private static final Range<Rational> POSITIVE_RATIONALS =
+        Range.create(new Rational(1, Integer.MAX_VALUE),
+                     new Rational(Integer.MAX_VALUE, 1));
+    private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
+    private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
+
+    // found stuff that is not supported by framework (=> this should not happen)
+    private static final int ERROR_UNRECOGNIZED   = (1 << 0);
+    // found profile/level for which we don't have capability estimates
+    private static final int ERROR_UNSUPPORTED    = (1 << 1);
+    // have not found any profile/level for which we don't have capability estimate
+    private static final int ERROR_NONE_SUPPORTED = (1 << 2);
+
+
     /**
      * Encapsulates the capabilities of a given codec component.
      * For example, what profile/level combinations it supports and what colorspaces
@@ -222,17 +259,6 @@
             return checkFeature(name, mFlagsRequired);
         }
 
-        private static class Feature {
-            public String mName;
-            public int mValue;
-            public boolean mDefault;
-            public Feature(String name, int value, boolean def) {
-                mName = name;
-                mValue = value;
-                mDefault = def;
-            }
-        }
-
         private static final Feature[] decoderFeatures = {
             new Feature(FEATURE_AdaptivePlayback, (1 << 0), true),
             new Feature(FEATURE_SecurePlayback,   (1 << 1), false),
@@ -312,1311 +338,54 @@
             return true;
         }
 
-        // errors while reading profile levels
-        private int mError;
-        // found stuff that is not supported by framework (=> this should not happen)
-        private static final int ERROR_UNRECOGNIZED   = (1 << 0);
-        // found profile/level for which we don't have capability estimates
-        private static final int ERROR_UNSUPPORTED    = (1 << 1);
-        // have not found any profile/level for which we don't have capability estimate
-        private static final int ERROR_NONE_SUPPORTED = (1 << 2);
-
-
-        // UTILITY METHODS
-        private static final Range<Integer> POSITIVE_INTEGERS =
-            Range.create(1, Integer.MAX_VALUE);
-        private static final Range<Long> POSITIVE_LONGS =
-            Range.create(1l, Long.MAX_VALUE);
-        private static final Range<Rational> POSITIVE_RATIONALS =
-            Range.create(new Rational(1, Integer.MAX_VALUE),
-                         new Rational(Integer.MAX_VALUE, 1));
-        private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
-        private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
+        // errors while reading profile levels - accessed from sister capabilities
+        int mError;
 
         private static final String TAG = "CodecCapabilities";
 
         // NEW-STYLE CAPABILITIES
+        private AudioCapabilities mAudioCaps;
+        private VideoCapabilities mVideoCaps;
+        private EncoderCapabilities mEncoderCaps;
+        private MediaFormat mDefaultFormat;
 
         /**
          * Returns a MediaFormat object with default values for configurations that have
          * defaults.
          */
-        public final MediaFormat getDefaultFormat() {
+        public MediaFormat getDefaultFormat() {
             return mDefaultFormat;
         }
-        private MediaFormat mDefaultFormat;
 
         /**
          * Returns the mime type for which this codec-capability object was created.
          */
-        public final String getMime() {
+        public String getMimeType() {
             return mMime;
         }
 
-        /**
-         * Returns the encoding capabilities or {@code null} if this is not an encoder.
-         */
-        public final EncoderCapabilities getEncoderCapabilities() {
-            return mEncoderCaps;
+        private boolean isAudio() {
+            return mAudioCaps != null;
         }
-        private EncoderCapabilities mEncoderCaps;
+
+        /**
+         * Returns the audio capabilities or {@code null} if this is not an audio codec.
+         */
+        public AudioCapabilities getAudioCapabilities() {
+            return mAudioCaps;
+        }
 
         private boolean isEncoder() {
             return mEncoderCaps != null;
         }
 
         /**
-         * A class that supports querying the encoding capabilities of a codec.
+         * Returns the encoding capabilities or {@code null} if this is not an encoder.
          */
-        public static final class EncoderCapabilities {
-            /**
-             * Returns the supported range of quality values.
-             */
-            public final Range<Integer> getQualityRange() {
-                return mQualityRange;
-            }
-
-            /**
-             * Returns the supported range of encoder complexity values.
-             * <p>
-             * Some codecs may support multiple complexity levels, where higher
-             * complexity values use more encoder tools (e.g. perform more
-             * intensive calculations) to improve the quality or the compression
-             * ratio.  Use a lower value to save power and/or time.
-             */
-            public final Range<Integer> getComplexityRange() {
-                return mComplexityRange;
-            }
-
-            /** Constant quality mode */
-            public static final int BITRATE_MODE_CQ = 0;
-            /** Variable bitrate mode */
-            public static final int BITRATE_MODE_VBR = 1;
-            /** Constant bitrate mode */
-            public static final int BITRATE_MODE_CBR = 2;
-
-            private static final Feature[] bitrates = new Feature[] {
-                new Feature("VBR", BITRATE_MODE_VBR, true),
-                new Feature("CBR", BITRATE_MODE_CBR, false),
-                new Feature("CQ",  BITRATE_MODE_CQ,  false)
-            };
-
-            private static int parseBitrateMode(String mode) {
-                for (Feature feat: bitrates) {
-                    if (feat.mName.equalsIgnoreCase(mode)) {
-                        return feat.mValue;
-                    }
-                }
-                return 0;
-            }
-
-            /**
-             * Query whether a bitrate mode is supported.
-             */
-            public final boolean isBitrateModeSupported(int mode) {
-                for (Feature feat: bitrates) {
-                    if (mode == feat.mValue) {
-                        return (mBitControl & (1 << mode)) != 0;
-                    }
-                }
-                return false;
-            }
-
-            private Range<Integer> mQualityRange;
-            private Range<Integer> mComplexityRange;
-            private CodecCapabilities mParent;
-
-            /* no public constructor */
-            private EncoderCapabilities() { }
-
-            /** @hide */
-            public static EncoderCapabilities create(
-                    MediaFormat info, CodecCapabilities parent) {
-                EncoderCapabilities caps = new EncoderCapabilities();
-                caps.init(info, parent);
-                return caps;
-            }
-
-            /** @hide */
-            public void init(MediaFormat info, CodecCapabilities parent) {
-                // no support for complexity or quality yet
-                mParent = parent;
-                mComplexityRange = Range.create(0, 0);
-                mQualityRange = Range.create(0, 0);
-                mBitControl = (1 << BITRATE_MODE_VBR);
-
-                applyLevelLimits();
-                parseFromInfo(info);
-            }
-
-            private void applyLevelLimits() {
-                String mime = mParent.getMime();
-                if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
-                    mComplexityRange = Range.create(0, 8);
-                    mBitControl = (1 << BITRATE_MODE_CQ);
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
-                        || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
-                        || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
-                        || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
-                        || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
-                    mBitControl = (1 << BITRATE_MODE_CBR);
-                }
-            }
-
-            private int mBitControl;
-            private Integer mDefaultComplexity;
-            private Integer mDefaultQuality;
-            private String mQualityScale;
-
-            private void parseFromInfo(MediaFormat info) {
-                Map<String, Object> map = info.getMap();
-
-                if (info.containsKey("complexity-range")) {
-                    mComplexityRange = Utils
-                            .parseIntRange(info.getString("complexity-range"), mComplexityRange);
-                    // TODO should we limit this to level limits?
-                }
-                if (info.containsKey("quality-range")) {
-                    mQualityRange = Utils
-                            .parseIntRange(info.getString("quality-range"), mQualityRange);
-                }
-                if (info.containsKey("feature-bitrate-control")) {
-                    for (String mode: info.getString("feature-bitrate-control").split(",")) {
-                        mBitControl |= parseBitrateMode(mode);
-                    }
-                }
-
-                try {
-                    mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default"));
-                } catch (NumberFormatException e) { }
-
-                try {
-                    mDefaultQuality = Integer.parseInt((String)map.get("quality-default"));
-                } catch (NumberFormatException e) { }
-
-                mQualityScale = (String)map.get("quality-scale");
-            }
-
-            private boolean supports(
-                    Integer complexity, Integer quality, Integer profile) {
-                boolean ok = true;
-                if (ok && complexity != null) {
-                    ok = mComplexityRange.contains(complexity);
-                }
-                if (ok && quality != null) {
-                    ok = mQualityRange.contains(quality);
-                }
-                if (ok && profile != null) {
-                    for (CodecProfileLevel pl: mParent.profileLevels) {
-                        if (pl.profile == profile) {
-                            profile = null;
-                            break;
-                        }
-                    }
-                    ok = profile == null;
-                }
-                return ok;
-            }
-
-            /** @hide */
-            public void setDefaultFormat(MediaFormat format) {
-                // don't list trivial quality/complexity as default for now
-                if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
-                        && mDefaultQuality != null) {
-                    format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality);
-                }
-                if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower())
-                        && mDefaultComplexity != null) {
-                    format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity);
-                }
-                // bitrates are listed in order of preference
-                for (Feature feat: bitrates) {
-                    if ((mBitControl & (1 << feat.mValue)) != 0) {
-                        format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue);
-                        break;
-                    }
-                }
-            }
-
-            /** @hide */
-            public boolean supportsFormat(MediaFormat format) {
-                final Map<String, Object> map = format.getMap();
-                final String mime = mParent.getMime();
-
-                Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE);
-                if (mode != null && !isBitrateModeSupported(mode)) {
-                    return false;
-                }
-
-                Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY);
-                if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) {
-                    Integer flacComplexity =
-                        (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL);
-                    if (complexity == null) {
-                        complexity = flacComplexity;
-                    } else if (flacComplexity != null && complexity != flacComplexity) {
-                        throw new IllegalArgumentException(
-                                "conflicting values for complexity and " +
-                                "flac-compression-level");
-                    }
-                }
-
-                // other audio parameters
-                Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
-                if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) {
-                    Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE);
-                    if (profile == null) {
-                        profile = aacProfile;
-                    } else if (aacProfile != null && aacProfile != profile) {
-                        throw new IllegalArgumentException(
-                                "conflicting values for profile and aac-profile");
-                    }
-                }
-
-                Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY);
-
-                return supports(complexity, quality, profile);
-            }
-        };
-
-        /**
-         * A class that supports querying basic capabilities of a codec.
-         */
-        public static class BaseCapabilities {
-            /**
-             * Returns the range of supported bitrates in bits/second.
-             */
-            public final Range<Integer> getBitrateRange() {
-                return mBitrateRange;
-            }
-
-            /** @hide */
-            protected Range<Integer> mBitrateRange;
-
-            /** @hide */
-            protected CodecCapabilities mParent;
-
-            /** @hide */
-            protected BaseCapabilities() {
-            }
-
-            /** @hide */
-            protected void init(MediaFormat info, CodecCapabilities parent) {
-                mParent = parent;
-                mBitrateRange = Range.create(0, Integer.MAX_VALUE);
-            }
+        public EncoderCapabilities getEncoderCapabilities() {
+            return mEncoderCaps;
         }
 
-        /**
-         * A class that supports querying the video capabilities of a codec.
-         */
-        public static final class VideoCapabilities extends BaseCapabilities {
-            private static final String TAG = "VideoCapabilities";
-            private Range<Integer> mHeightRange;
-            private Range<Integer> mWidthRange;
-            private Range<Integer> mBlockCountRange;
-            private Range<Integer> mHorizontalBlockRange;
-            private Range<Integer> mVerticalBlockRange;
-            private Range<Rational> mAspectRatioRange;
-            private Range<Rational> mBlockAspectRatioRange;
-            private Range<Long> mBlocksPerSecondRange;
-            private Range<Integer> mFrameRateRange;
-
-            private int mBlockWidth;
-            private int mBlockHeight;
-            private int mWidthAlignment;
-            private int mHeightAlignment;
-            private int mSmallerDimensionUpperLimit;
-
-            /**
-             * Returns the range of supported video widths.
-             */
-            public final Range<Integer> getSupportedWidths() {
-                return mWidthRange;
-            }
-
-            /**
-             * Returns the range of supported video heights.
-             */
-            public final Range<Integer> getSupportedHeights() {
-                return mHeightRange;
-            }
-
-            /**
-             * Returns the alignment requirement for video width.
-             */
-            public final int getWidthAlignment() {
-                return mWidthAlignment;
-            }
-
-            /**
-             * Returns the alignment requirement for video height.
-             */
-            public final int getHeightAlignment() {
-                return mHeightAlignment;
-            }
-
-            /**
-             * Return the upper limit on the smaller dimension of width or height.
-             * <p></p>
-             * Some codecs have a limit on the smaller dimension, whether it be
-             * the width or the height.  E.g. a codec may only be able to handle
-             * up to 1920x1080 both in landscape and portrait mode (1080x1920).
-             * In this case the maximum width and height are both 1920, but the
-             * smaller dimension limit will be 1080. For other codecs, this is
-             * {@code Math.min(getSupportedWidths().getUpper(),
-             * getSupportedHeights().getUpper())}.
-             *
-             * @hide
-             */
-            public int getSmallerDimensionUpperLimit() {
-                return mSmallerDimensionUpperLimit;
-            }
-
-            /**
-             * Returns the range of supported frame rates.
-             * <p>
-             * This is not a performance indicator.  Rather, it expresses the
-             * limits specified in the coding standard, based on the complexities
-             * of encoding material for later playback at a certain frame rate,
-             * or the decoding of such material in non-realtime.
-             */
-            public final Range<Integer> getSupportedFrameRates() {
-                return mFrameRateRange;
-            }
-
-            /**
-             * Returns the range of supported video widths for a video height.
-             * @param height the height of the video
-             */
-            public final Range<Integer> getSupportedWidthsFor(int height) {
-                try {
-                    Range<Integer> range = mWidthRange;
-                    if (!mHeightRange.contains(height)
-                            || (height % mHeightAlignment) != 0) {
-                        throw new IllegalArgumentException("unsupported height");
-                    }
-                    final int heightInBlocks = Utils.divUp(height, mBlockHeight);
-
-                    // constrain by block count and by block aspect ratio
-                    final int minWidthInBlocks = Math.max(
-                            Utils.divUp(mBlockCountRange.getLower(), heightInBlocks),
-                            (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue()
-                                    * heightInBlocks));
-                    final int maxWidthInBlocks = Math.min(
-                            mBlockCountRange.getUpper() / heightInBlocks,
-                            (int)(mBlockAspectRatioRange.getUpper().doubleValue()
-                                    * heightInBlocks));
-                    range = range.intersect(
-                            (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment,
-                            maxWidthInBlocks * mBlockWidth);
-
-                    // constrain by smaller dimension limit
-                    if (height > mSmallerDimensionUpperLimit) {
-                        range = range.intersect(1, mSmallerDimensionUpperLimit);
-                    }
-
-                    // constrain by aspect ratio
-                    range = range.intersect(
-                            (int)Math.ceil(mAspectRatioRange.getLower().doubleValue()
-                                    * height),
-                            (int)(mAspectRatioRange.getUpper().doubleValue() * height));
-                    return range;
-                } catch (IllegalArgumentException e) {
-                    // should not be here
-                    Log.w(TAG, "could not get supported widths for " + height , e);
-                    throw new IllegalArgumentException("unsupported height");
-                }
-            }
-
-            /**
-             * Returns the range of supported video heights for a video width
-             * @param width the width of the video
-             */
-            public final Range<Integer> getSupportedHeightsFor(int width) {
-                try {
-                    Range<Integer> range = mHeightRange;
-                    if (!mWidthRange.contains(width)
-                            || (width % mWidthAlignment) != 0) {
-                        throw new IllegalArgumentException("unsupported width");
-                    }
-                    final int widthInBlocks = Utils.divUp(width, mBlockWidth);
-
-                    // constrain by block count and by block aspect ratio
-                    final int minHeightInBlocks = Math.max(
-                            Utils.divUp(mBlockCountRange.getLower(), widthInBlocks),
-                            (int)Math.ceil(widthInBlocks /
-                                    mBlockAspectRatioRange.getUpper().doubleValue()));
-                    final int maxHeightInBlocks = Math.min(
-                            mBlockCountRange.getUpper() / widthInBlocks,
-                            (int)(widthInBlocks /
-                                    mBlockAspectRatioRange.getLower().doubleValue()));
-                    range = range.intersect(
-                            (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment,
-                            maxHeightInBlocks * mBlockHeight);
-
-                    // constrain by smaller dimension limit
-                    if (width > mSmallerDimensionUpperLimit) {
-                        range = range.intersect(1, mSmallerDimensionUpperLimit);
-                    }
-
-                    // constrain by aspect ratio
-                    range = range.intersect(
-                            (int)Math.ceil(width /
-                                    mAspectRatioRange.getUpper().doubleValue()),
-                            (int)(width / mAspectRatioRange.getLower().doubleValue()));
-                    return range;
-                } catch (IllegalArgumentException e) {
-                    // should not be here
-                    Log.w(TAG, "could not get supported heights for " + width , e);
-                    throw new IllegalArgumentException("unsupported width");
-                }
-            }
-
-            /**
-             * Returns the range of supported video frame rates for a video size.
-             * <p>
-             * This is not a performance indicator.  Rather, it expresses the limits specified in
-             * the coding standard, based on the complexities of encoding material of a given
-             * size for later playback at a certain frame rate, or the decoding of such material
-             * in non-realtime.
-
-             * @param width the width of the video
-             * @param height the height of the video
-             */
-            public final Range<Double> getSupportedFrameRatesFor(int width, int height) {
-                Range<Integer> range = mHeightRange;
-                if (!supports(width, height, null)) {
-                    throw new IllegalArgumentException("unsupported size");
-                }
-                final int blockCount =
-                    Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
-
-                return Range.create(
-                        Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount,
-                                (double) mFrameRateRange.getLower()),
-                        Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount,
-                                (double) mFrameRateRange.getUpper()));
-            }
-
-            /**
-             * Returns whether a given video size ({@code width} and
-             * {@code height}) and {@code frameRate} combination is supported.
-             */
-            public final boolean areSizeAndRateSupported(
-                    int width, int height, double frameRate) {
-                return supports(width, height, frameRate);
-            }
-
-            /**
-             * Returns whether a given video size ({@code width} and
-             * {@code height}) is supported.
-             */
-            public final boolean isSizeSupported(int width, int height) {
-                return supports(width, height, null);
-            }
-
-            private final boolean supports(
-                    Integer width, Integer height, Double rate) {
-                boolean ok = true;
-
-                if (ok && width != null) {
-                    ok = mWidthRange.contains(width)
-                            && (width % mWidthAlignment == 0);
-                }
-                if (ok && height != null) {
-                    ok = mHeightRange.contains(height)
-                            && (height % mHeightAlignment == 0);
-                }
-                if (ok && rate != null) {
-                    ok = mFrameRateRange.contains(Utils.intRangeFor(rate));
-                }
-                if (ok && height != null && width != null) {
-                    ok = Math.min(height, width) <= mSmallerDimensionUpperLimit;
-
-                    final int widthInBlocks = Utils.divUp(width, mBlockWidth);
-                    final int heightInBlocks = Utils.divUp(height, mBlockHeight);
-                    final int blockCount = widthInBlocks * heightInBlocks;
-                    ok = ok && mBlockCountRange.contains(blockCount)
-                            && mBlockAspectRatioRange.contains(
-                                    new Rational(widthInBlocks, heightInBlocks))
-                            && mAspectRatioRange.contains(new Rational(width, height));
-                    if (ok && rate != null) {
-                        double blocksPerSec = blockCount * rate;
-                        ok = mBlocksPerSecondRange.contains(
-                                Utils.longRangeFor(blocksPerSec));
-                    }
-                }
-                return ok;
-            }
-
-            /**
-             * @hide
-             * @throws java.lang.ClassCastException */
-            public boolean supportsFormat(MediaFormat format) {
-                final Map<String, Object> map = format.getMap();
-                Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH);
-                Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
-                Double rate = (Double)map.get(MediaFormat.KEY_FRAME_RATE);
-
-                // we ignore color-format for now as it is not reliably reported by codec
-
-                return supports(width, height, rate);
-            }
-
-            /* no public constructor */
-            private VideoCapabilities() { }
-
-            /** @hide */
-            public static VideoCapabilities create(
-                    MediaFormat info, CodecCapabilities parent) {
-                VideoCapabilities caps = new VideoCapabilities();
-                caps.init(info, parent);
-                return caps;
-            }
-
-            /** @hide */
-            public void init(MediaFormat info, CodecCapabilities parent) {
-                super.init(info, parent);
-                initWithPlatformLimits();
-                applyLevelLimits();
-                parseFromInfo(info);
-                updateLimits();
-            }
-
-            /** @hide */
-            public Size getBlockSize() {
-                return new Size(mBlockWidth, mBlockHeight);
-            }
-
-            /** @hide */
-            public Range<Integer> getBlockCountRange() {
-                return mBlockCountRange;
-            }
-
-            /** @hide */
-            public Range<Long> getBlocksPerSecondRange() {
-                return mBlocksPerSecondRange;
-            }
-
-            /** @hide */
-            public Range<Rational> getAspectRatioRange(boolean blocks) {
-                return blocks ? mBlockAspectRatioRange : mAspectRatioRange;
-            }
-
-            private void initWithPlatformLimits() {
-                mWidthRange  = SIZE_RANGE;
-                mHeightRange = SIZE_RANGE;
-                mFrameRateRange = FRAME_RATE_RANGE;
-
-                mHorizontalBlockRange = SIZE_RANGE;
-                mVerticalBlockRange   = SIZE_RANGE;
-
-                // full positive ranges are supported as these get calculated
-                mBlockCountRange      = POSITIVE_INTEGERS;
-                mBlocksPerSecondRange = POSITIVE_LONGS;
-
-                mBlockAspectRatioRange = POSITIVE_RATIONALS;
-                mAspectRatioRange      = POSITIVE_RATIONALS;
-
-                // YUV 4:2:0 requires 2:2 alignment
-                mWidthAlignment = 2;
-                mHeightAlignment = 2;
-                mBlockWidth = 2;
-                mBlockHeight = 2;
-                mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
-            }
-
-            private void parseFromInfo(MediaFormat info) {
-                final Map<String, Object> map = info.getMap();
-                Size blockSize = new Size(mBlockWidth, mBlockHeight);
-                Size alignment = new Size(mWidthAlignment, mHeightAlignment);
-                Range<Integer> counts = null, widths = null, heights = null;
-                Range<Integer> frameRates = null;
-                Range<Long> blockRates = null;
-                Range<Rational> ratios = null, blockRatios = null;
-
-                blockSize = Utils.parseSize(map.get("block-size"), blockSize);
-                alignment = Utils.parseSize(map.get("alignment"), alignment);
-                counts = Utils.parseIntRange(map.get("block-count-range"), null);
-                blockRates =
-                    Utils.parseLongRange(map.get("blocks-per-second-range"), null);
-                {
-                    Object o = map.get("size-range");
-                    Pair<Size, Size> sizeRange = Utils.parseSizeRange(o);
-                    if (sizeRange != null) {
-                        try {
-                            widths = Range.create(
-                                    sizeRange.first.getWidth(),
-                                    sizeRange.second.getWidth());
-                            heights = Range.create(
-                                    sizeRange.first.getHeight(),
-                                    sizeRange.second.getHeight());
-                        } catch (IllegalArgumentException e) {
-                            Log.w(TAG, "could not parse size range '" + o + "'");
-                            widths = null;
-                            heights = null;
-                        }
-                    }
-                }
-                // for now this just means using the smaller max size as 2nd
-                // upper limit.
-                // for now we are keeping the profile specific "width/height
-                // in macroblocks" limits.
-                if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) {
-                    if (widths != null) {
-                        mSmallerDimensionUpperLimit =
-                            Math.min(widths.getUpper(), heights.getUpper());
-                        widths = heights = widths.extend(heights);
-                    } else {
-                        Log.w(TAG, "feature can-swap-width-height is best used with size-range");
-                        mSmallerDimensionUpperLimit =
-                            Math.min(mWidthRange.getUpper(), mHeightRange.getUpper());
-                        mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
-                    }
-                }
-
-                ratios = Utils.parseRationalRange(
-                        map.get("block-aspect-ratio-range"), null);
-                blockRatios = Utils.parseRationalRange(
-                        map.get("pixel-aspect-ratio-range"), null);
-                frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null);
-                if (frameRates != null) {
-                    try {
-                        frameRates = frameRates.intersect(FRAME_RATE_RANGE);
-                    } catch (IllegalArgumentException e) {
-                        Log.w(TAG, "frame rate range (" + frameRates
-                                + ") is out of limits: " + FRAME_RATE_RANGE);
-                        frameRates = null;
-                    }
-                }
-
-                checkPowerOfTwo(
-                        blockSize.getWidth(), "block-size width must be power of two");
-                checkPowerOfTwo(
-                        blockSize.getHeight(), "block-size height must be power of two");
-
-                checkPowerOfTwo(
-                        alignment.getWidth(), "alignment width must be power of two");
-                checkPowerOfTwo(
-                        alignment.getHeight(), "alignment height must be power of two");
-
-                // update block-size and alignment
-                applyMacroBlockLimits(
-                        Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
-                        Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(),
-                        alignment.getWidth(), alignment.getHeight());
-
-                if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
-                    // codec supports profiles that we don't know.
-                    // Use supplied values clipped to platform limits
-                    if (widths != null) {
-                        mWidthRange = SIZE_RANGE.intersect(widths);
-                    }
-                    if (heights != null) {
-                        mHeightRange = SIZE_RANGE.intersect(heights);
-                    }
-                    if (counts != null) {
-                        mBlockCountRange = POSITIVE_INTEGERS.intersect(
-                                Utils.factorRange(counts, mBlockWidth * mBlockHeight
-                                        / blockSize.getWidth() / blockSize.getHeight()));
-                    }
-                    if (blockRates != null) {
-                        mBlocksPerSecondRange = POSITIVE_LONGS.intersect(
-                                Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
-                                        / blockSize.getWidth() / blockSize.getHeight()));
-                    }
-                    if (blockRatios != null) {
-                        mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
-                                Utils.scaleRange(blockRatios,
-                                        mBlockHeight / blockSize.getHeight(),
-                                        mBlockWidth / blockSize.getWidth()));
-                    }
-                    if (ratios != null) {
-                        mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios);
-                    }
-                    if (frameRates != null) {
-                        mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates);
-                    }
-                } else {
-                    // no unsupported profile/levels, so restrict values to known limits
-                    if (widths != null) {
-                        mWidthRange = mWidthRange.intersect(widths);
-                    }
-                    if (heights != null) {
-                        mHeightRange = mHeightRange.intersect(heights);
-                    }
-                    if (counts != null) {
-                        mBlockCountRange = mBlockCountRange.intersect(
-                                Utils.factorRange(counts, mBlockWidth * mBlockHeight
-                                        / blockSize.getWidth() / blockSize.getHeight()));
-                    }
-                    if (blockRates != null) {
-                        mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
-                                Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
-                                        / blockSize.getWidth() / blockSize.getHeight()));
-                    }
-                    if (blockRatios != null) {
-                        mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
-                                Utils.scaleRange(blockRatios,
-                                        mBlockHeight / blockSize.getHeight(),
-                                        mBlockWidth / blockSize.getWidth()));
-                    }
-                    if (ratios != null) {
-                        mAspectRatioRange = mAspectRatioRange.intersect(ratios);
-                    }
-                    if (frameRates != null) {
-                        mFrameRateRange = mFrameRateRange.intersect(frameRates);
-                    }
-                }
-                updateLimits();
-            }
-
-            private int checkPowerOfTwo(int value, String message) {
-                if ((value & (value - 1)) != 0) {
-                    throw new IllegalArgumentException(message);
-                }
-                return value;
-            }
-
-            private void applyBlockLimits(
-                    int blockWidth, int blockHeight,
-                    Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) {
-                checkPowerOfTwo(blockWidth, "blockWidth must be a power of two");
-                checkPowerOfTwo(blockHeight, "blockHeight must be a power of two");
-
-                final int newBlockWidth = Math.max(blockWidth, mBlockWidth);
-                final int newBlockHeight = Math.max(blockHeight, mBlockHeight);
-
-                // factor will always be a power-of-2
-                int factor =
-                    newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight;
-                if (factor != 1) {
-                    mBlockCountRange = Utils.factorRange(mBlockCountRange, factor);
-                    mBlocksPerSecondRange = Utils.factorRange(
-                            mBlocksPerSecondRange, factor);
-                    mBlockAspectRatioRange = Utils.scaleRange(
-                            mBlockAspectRatioRange,
-                            newBlockHeight / mBlockHeight,
-                            newBlockWidth / mBlockWidth);
-                    mHorizontalBlockRange = Utils.factorRange(
-                            mHorizontalBlockRange, newBlockWidth / mBlockWidth);
-                    mVerticalBlockRange = Utils.factorRange(
-                            mVerticalBlockRange, newBlockHeight / mBlockHeight);
-                }
-                factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight;
-                if (factor != 1) {
-                    counts = Utils.factorRange(counts, factor);
-                    rates = Utils.factorRange(rates, factor);
-                    ratios = Utils.scaleRange(
-                            ratios, newBlockHeight / blockHeight,
-                            newBlockWidth / blockWidth);
-                }
-                mBlockCountRange = mBlockCountRange.intersect(counts);
-                mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates);
-                mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios);
-                mBlockWidth = newBlockWidth;
-                mBlockHeight = newBlockHeight;
-            }
-
-            private void applyAlignment(int widthAlignment, int heightAlignment) {
-                checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two");
-                checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two");
-
-                if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) {
-                    // maintain assumption that 0 < alignment <= block-size
-                    applyBlockLimits(
-                            Math.max(widthAlignment, mBlockWidth),
-                            Math.max(heightAlignment, mBlockHeight),
-                            POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS);
-                }
-
-                mWidthAlignment = Math.max(widthAlignment, mWidthAlignment);
-                mHeightAlignment = Math.max(heightAlignment, mHeightAlignment);
-
-                mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment);
-                mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment);
-            }
-
-            private void updateLimits() {
-                // pixels -> blocks <- counts
-                mHorizontalBlockRange = mHorizontalBlockRange.intersect(
-                        Utils.factorRange(mWidthRange, mBlockWidth));
-                mHorizontalBlockRange = mHorizontalBlockRange.intersect(
-                        Range.create(
-                                mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(),
-                                mBlockCountRange.getUpper() / mVerticalBlockRange.getLower()));
-                mVerticalBlockRange = mVerticalBlockRange.intersect(
-                        Utils.factorRange(mHeightRange, mBlockHeight));
-                mVerticalBlockRange = mVerticalBlockRange.intersect(
-                        Range.create(
-                                mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(),
-                                mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower()));
-                mBlockCountRange = mBlockCountRange.intersect(
-                        Range.create(
-                                mHorizontalBlockRange.getLower()
-                                        * mVerticalBlockRange.getLower(),
-                                mHorizontalBlockRange.getUpper()
-                                        * mVerticalBlockRange.getUpper()));
-                mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
-                        new Rational(
-                                mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()),
-                        new Rational(
-                                mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower()));
-
-                // blocks -> pixels
-                mWidthRange = mWidthRange.intersect(
-                        (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment,
-                        mHorizontalBlockRange.getUpper() * mBlockWidth);
-                mHeightRange = mHeightRange.intersect(
-                        (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment,
-                        mVerticalBlockRange.getUpper() * mBlockHeight);
-                mAspectRatioRange = mAspectRatioRange.intersect(
-                        new Rational(mWidthRange.getLower(), mHeightRange.getUpper()),
-                        new Rational(mWidthRange.getUpper(), mHeightRange.getLower()));
-
-                mSmallerDimensionUpperLimit = Math.min(
-                        mSmallerDimensionUpperLimit,
-                        Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()));
-
-                // blocks -> rate
-                mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
-                        mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(),
-                        mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper());
-                mFrameRateRange = mFrameRateRange.intersect(
-                        (int)(mBlocksPerSecondRange.getLower()
-                                / mBlockCountRange.getUpper()),
-                        (int)(mBlocksPerSecondRange.getUpper()
-                                / (double)mBlockCountRange.getLower()));
-            }
-
-            private void applyMacroBlockLimits(
-                    int maxHorizontalBlocks, int maxVerticalBlocks,
-                    int maxBlocks, long maxBlocksPerSecond,
-                    int blockWidth, int blockHeight,
-                    int widthAlignment, int heightAlignment) {
-                applyAlignment(widthAlignment, heightAlignment);
-                applyBlockLimits(
-                        blockWidth, blockHeight, Range.create(1, maxBlocks),
-                        Range.create(1L, maxBlocksPerSecond),
-                        Range.create(
-                                new Rational(1, maxVerticalBlocks),
-                                new Rational(maxHorizontalBlocks, 1)));
-                mHorizontalBlockRange =
-                        mHorizontalBlockRange.intersect(
-                                1, maxHorizontalBlocks / (mBlockWidth / blockWidth));
-                mVerticalBlockRange =
-                        mVerticalBlockRange.intersect(
-                                1, maxVerticalBlocks / (mBlockHeight / blockHeight));
-            }
-
-            private void applyLevelLimits() {
-                int maxBlocksPerSecond = 0;
-                int maxBlocks = 0;
-                int maxBps = 0;
-                int maxDPBBlocks = 0;
-
-                int errors = ERROR_NONE_SUPPORTED;
-                CodecProfileLevel[] profileLevels = mParent.profileLevels;
-                String mime = mParent.getMime();
-
-                if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
-                    maxBlocks = 99;
-                    maxBlocksPerSecond = 1485;
-                    maxBps = 64000;
-                    maxDPBBlocks = 396;
-                    for (CodecProfileLevel profileLevel: profileLevels) {
-                        int MBPS = 0, FS = 0, BR = 0, DPB = 0;
-                        boolean supported = true;
-                        switch (profileLevel.level) {
-                            case CodecProfileLevel.AVCLevel1:
-                                MBPS =    1485; FS =    99; BR =     64; DPB =    396; break;
-                            case CodecProfileLevel.AVCLevel1b:
-                                MBPS =    1485; FS =    99; BR =    128; DPB =    396; break;
-                            case CodecProfileLevel.AVCLevel11:
-                                MBPS =    3000; FS =   396; BR =    192; DPB =    900; break;
-                            case CodecProfileLevel.AVCLevel12:
-                                MBPS =    6000; FS =   396; BR =    384; DPB =   2376; break;
-                            case CodecProfileLevel.AVCLevel13:
-                                MBPS =   11880; FS =   396; BR =    768; DPB =   2376; break;
-                            case CodecProfileLevel.AVCLevel2:
-                                MBPS =   11880; FS =   396; BR =   2000; DPB =   2376; break;
-                            case CodecProfileLevel.AVCLevel21:
-                                MBPS =   19800; FS =   792; BR =   4000; DPB =   4752; break;
-                            case CodecProfileLevel.AVCLevel22:
-                                MBPS =   20250; FS =  1620; BR =   4000; DPB =   8100; break;
-                            case CodecProfileLevel.AVCLevel3:
-                                MBPS =   40500; FS =  1620; BR =  10000; DPB =   8100; break;
-                            case CodecProfileLevel.AVCLevel31:
-                                MBPS =  108000; FS =  3600; BR =  14000; DPB =  18000; break;
-                            case CodecProfileLevel.AVCLevel32:
-                                MBPS =  216000; FS =  5120; BR =  20000; DPB =  20480; break;
-                            case CodecProfileLevel.AVCLevel4:
-                                MBPS =  245760; FS =  8192; BR =  20000; DPB =  32768; break;
-                            case CodecProfileLevel.AVCLevel41:
-                                MBPS =  245760; FS =  8192; BR =  50000; DPB =  32768; break;
-                            case CodecProfileLevel.AVCLevel42:
-                                MBPS =  522240; FS =  8704; BR =  50000; DPB =  34816; break;
-                            case CodecProfileLevel.AVCLevel5:
-                                MBPS =  589824; FS = 22080; BR = 135000; DPB = 110400; break;
-                            case CodecProfileLevel.AVCLevel51:
-                                MBPS =  983040; FS = 36864; BR = 240000; DPB = 184320; break;
-                            case CodecProfileLevel.AVCLevel52:
-                                MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
-                            default:
-                                Log.w(TAG, "Unrecognized level "
-                                        + profileLevel.level + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        switch (profileLevel.profile) {
-                            case CodecProfileLevel.AVCProfileHigh:
-                                BR *= 1250; break;
-                            case CodecProfileLevel.AVCProfileHigh10:
-                                BR *= 3000; break;
-                            case CodecProfileLevel.AVCProfileExtended:
-                            case CodecProfileLevel.AVCProfileHigh422:
-                            case CodecProfileLevel.AVCProfileHigh444:
-                                Log.w(TAG, "Unsupported profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNSUPPORTED;
-                                supported = false;
-                                // fall through - treat as base profile
-                            case CodecProfileLevel.AVCProfileBaseline:
-                            case CodecProfileLevel.AVCProfileMain:
-                                BR *= 1000; break;
-                            default:
-                                Log.w(TAG, "Unrecognized profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                                BR *= 1000;
-                        }
-                        if (supported) {
-                            errors &= ~ERROR_NONE_SUPPORTED;
-                        }
-                        maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
-                        maxBlocks = Math.max(FS, maxBlocks);
-                        maxBps = Math.max(BR, maxBps);
-                        maxDPBBlocks = Math.max(maxDPBBlocks, DPB);
-                    }
-
-                    int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
-                    applyMacroBlockLimits(
-                            maxLengthInBlocks, maxLengthInBlocks,
-                            maxBlocks, maxBlocksPerSecond,
-                            16 /* blockWidth */, 16 /* blockHeight */,
-                            1 /* widthAlignment */, 1 /* heightAlignment */);
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
-                    int maxWidth = 11, maxHeight = 9, maxRate = 15;
-                    maxBlocks = 99;
-                    maxBlocksPerSecond = 1485;
-                    maxBps = 64000;
-                    for (CodecProfileLevel profileLevel: profileLevels) {
-                        int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
-                        boolean supported = true;
-                        switch (profileLevel.profile) {
-                            case CodecProfileLevel.MPEG4ProfileSimple:
-                                switch (profileLevel.level) {
-                                    case CodecProfileLevel.MPEG4Level0:
-                                        FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
-                                    case CodecProfileLevel.MPEG4Level1:
-                                        FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
-                                    case CodecProfileLevel.MPEG4Level0b:
-                                        FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR = 128; break;
-                                    case CodecProfileLevel.MPEG4Level2:
-                                        FR = 30; W = 22; H = 18; MBPS =  5940; FS = 396; BR = 128; break;
-                                    case CodecProfileLevel.MPEG4Level3:
-                                        FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break;
-                                    case CodecProfileLevel.MPEG4Level4:
-                                    case CodecProfileLevel.MPEG4Level4a:
-                                    case CodecProfileLevel.MPEG4Level5:
-                                        // While MPEG4 SP does not have level 4 or 5, some vendors
-                                        // report it. Use the same limits as level 3, but mark as
-                                        // unsupported.
-                                        FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384;
-                                        supported = false;
-                                        break;
-                                    default:
-                                        Log.w(TAG, "Unrecognized profile/level "
-                                                + profileLevel.profile + "/"
-                                                + profileLevel.level + " for " + mime);
-                                        errors |= ERROR_UNRECOGNIZED;
-                                }
-                                break;
-                            case CodecProfileLevel.MPEG4ProfileAdvancedSimple:
-                                switch (profileLevel.level) {
-                                    case CodecProfileLevel.MPEG4Level0:
-                                    case CodecProfileLevel.MPEG4Level1:
-                                        FR = 30; W = 11; H =  9; MBPS =  2970; FS =   99; BR =  128; break;
-                                    case CodecProfileLevel.MPEG4Level2:
-                                        FR = 30; W = 22; H = 18; MBPS =  5940; FS =  396; BR =  384; break;
-                                    case CodecProfileLevel.MPEG4Level3:
-                                        FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR =  768; break;
-                                    // case CodecProfileLevel.MPEG4Level3b:
-                                    // TODO: MPEG4 level 3b is not defined in OMX
-                                    //  MBPS = 11880; FS =  396; BR = 1500; break;
-                                    case CodecProfileLevel.MPEG4Level4:
-                                    case CodecProfileLevel.MPEG4Level4a:
-                                        // TODO: MPEG4 level 4a is not defined in spec
-                                        FR = 30; W = 44; H = 36; MBPS = 23760; FS =  792; BR = 3000; break;
-                                    case CodecProfileLevel.MPEG4Level5:
-                                        FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break;
-                                    default:
-                                        Log.w(TAG, "Unrecognized profile/level "
-                                                + profileLevel.profile + "/"
-                                                + profileLevel.level + " for " + mime);
-                                        errors |= ERROR_UNRECOGNIZED;
-                                }
-                                break;
-                            case CodecProfileLevel.MPEG4ProfileMain:             // 2-4
-                            case CodecProfileLevel.MPEG4ProfileNbit:             // 2
-                            case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4
-                            case CodecProfileLevel.MPEG4ProfileCoreScalable:     // 1-3
-                            case CodecProfileLevel.MPEG4ProfileAdvancedCoding:   // 1-4
-                            case CodecProfileLevel.MPEG4ProfileCore:             // 1-2
-                            case CodecProfileLevel.MPEG4ProfileAdvancedCore:     // 1-4
-                            case CodecProfileLevel.MPEG4ProfileSimpleScalable:   // 0-2
-                            case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3
-                            case CodecProfileLevel.MPEG4ProfileHybrid:           // 1-2
-                            case CodecProfileLevel.MPEG4ProfileBasicAnimated:    // 1-2
-                            case CodecProfileLevel.MPEG4ProfileScalableTexture:  // 1
-                            case CodecProfileLevel.MPEG4ProfileSimpleFace:       // 1-2
-                            case CodecProfileLevel.MPEG4ProfileSimpleFBA:        // 1-2
-                                Log.i(TAG, "Unsupported profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNSUPPORTED;
-                                supported = false;
-                                break;
-                            default:
-                                Log.w(TAG, "Unrecognized profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        if (supported) {
-                            errors &= ~ERROR_NONE_SUPPORTED;
-                        }
-                        maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
-                        maxBlocks = Math.max(FS, maxBlocks);
-                        maxBps = Math.max(BR * 1000, maxBps);
-                        maxWidth = Math.max(W, maxWidth);
-                        maxHeight = Math.max(H, maxHeight);
-                        maxRate = Math.max(FR, maxRate);
-                    }
-                    applyMacroBlockLimits(maxWidth, maxHeight,
-                            maxBlocks, maxBlocksPerSecond,
-                            16 /* blockWidth */, 16 /* blockHeight */,
-                            1 /* widthAlignment */, 1 /* heightAlignment */);
-                    mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
-                    int maxWidth = 11, maxHeight = 9, maxRate = 15;
-                    maxBlocks = 99;
-                    maxBlocksPerSecond = 1485;
-                    maxBps = 64000;
-                    for (CodecProfileLevel profileLevel: profileLevels) {
-                        int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0;
-                        switch (profileLevel.level) {
-                            case CodecProfileLevel.H263Level10:
-                                FR = 15; W = 11; H =  9; BR =   1; MBPS =  W * H * FR; break;
-                            case CodecProfileLevel.H263Level20:
-                                // only supports CIF, 0..QCIF
-                                FR = 30; W = 22; H = 18; BR =   2; MBPS =  W * H * FR; break;
-                            case CodecProfileLevel.H263Level30:
-                                // only supports CIF, 0..QCIF
-                                FR = 30; W = 22; H = 18; BR =   6; MBPS =  W * H * FR; break;
-                            case CodecProfileLevel.H263Level40:
-                                // only supports CIF, 0..QCIF
-                                FR = 30; W = 22; H = 18; BR =  32; MBPS =  W * H * FR; break;
-                            case CodecProfileLevel.H263Level45:
-                                // only implies level 10 support
-                                FR = 30; W = 11; H =  9; BR =   2; MBPS =  W * H * FR; break;
-                            case CodecProfileLevel.H263Level50:
-                                // only supports 50fps for H > 15
-                                FR = 60; W = 22; H = 18; BR =  64; MBPS =  W * H * 50; break;
-                            case CodecProfileLevel.H263Level60:
-                                // only supports 50fps for H > 15
-                                FR = 60; W = 45; H = 18; BR = 128; MBPS =  W * H * 50; break;
-                            case CodecProfileLevel.H263Level70:
-                                // only supports 50fps for H > 30
-                                FR = 60; W = 45; H = 36; BR = 256; MBPS =  W * H * 50; break;
-                            default:
-                                Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile
-                                        + "/" + profileLevel.level + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        switch (profileLevel.profile) {
-                            case CodecProfileLevel.H263ProfileBackwardCompatible:
-                            case CodecProfileLevel.H263ProfileBaseline:
-                            case CodecProfileLevel.H263ProfileH320Coding:
-                            case CodecProfileLevel.H263ProfileHighCompression:
-                            case CodecProfileLevel.H263ProfileHighLatency:
-                            case CodecProfileLevel.H263ProfileInterlace:
-                            case CodecProfileLevel.H263ProfileInternet:
-                            case CodecProfileLevel.H263ProfileISWV2:
-                            case CodecProfileLevel.H263ProfileISWV3:
-                                break;
-                            default:
-                                Log.w(TAG, "Unrecognized profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        errors &= ~ERROR_NONE_SUPPORTED;
-                        maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
-                        maxBlocks = Math.max(W * H, maxBlocks);
-                        maxBps = Math.max(BR * 64000, maxBps);
-                        maxWidth = Math.max(W, maxWidth);
-                        maxHeight = Math.max(H, maxHeight);
-                        maxRate = Math.max(FR, maxRate);
-                    }
-                    applyMacroBlockLimits(maxWidth, maxHeight,
-                            maxBlocks, maxBlocksPerSecond,
-                            16 /* blockWidth */, 16 /* blockHeight */,
-                            1 /* widthAlignment */, 1 /* heightAlignment */);
-                    mFrameRateRange = Range.create(1, maxRate);
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ||
-                        mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-                    maxBlocks = maxBlocksPerSecond = Integer.MAX_VALUE;
-
-                    // TODO: set to 100Mbps for now, need a number for VPX
-                    maxBps = 100000000;
-
-                    // profile levels are not indicative for VPx, but verify
-                    // them nonetheless
-                    for (CodecProfileLevel profileLevel: profileLevels) {
-                        switch (profileLevel.level) {
-                            case CodecProfileLevel.VP8Level_Version0:
-                            case CodecProfileLevel.VP8Level_Version1:
-                            case CodecProfileLevel.VP8Level_Version2:
-                            case CodecProfileLevel.VP8Level_Version3:
-                                break;
-                            default:
-                                Log.w(TAG, "Unrecognized level "
-                                        + profileLevel.level + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        switch (profileLevel.profile) {
-                            case CodecProfileLevel.VP8ProfileMain:
-                                break;
-                            default:
-                                Log.w(TAG, "Unrecognized profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        errors &= ~ERROR_NONE_SUPPORTED;
-                    }
-
-                    final int blockSize =
-                        mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8;
-                    applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
-                            maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
-                            1 /* widthAlignment */, 1 /* heightAlignment */);
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
-                    maxBlocks = 36864;
-                    maxBlocksPerSecond = maxBlocks * 15;
-                    maxBps = 128000;
-                    for (CodecProfileLevel profileLevel: profileLevels) {
-                        double FR = 0;
-                        int FS = 0;
-                        int BR = 0;
-                        switch (profileLevel.level) {
-                            case CodecProfileLevel.HEVCMainTierLevel1:
-                            case CodecProfileLevel.HEVCHighTierLevel1:
-                                FR =    15; FS =    36864; BR =    128; break;
-                            case CodecProfileLevel.HEVCMainTierLevel2:
-                            case CodecProfileLevel.HEVCHighTierLevel2:
-                                FR =    30; FS =   122880; BR =   1500; break;
-                            case CodecProfileLevel.HEVCMainTierLevel21:
-                            case CodecProfileLevel.HEVCHighTierLevel21:
-                                FR =    30; FS =   245760; BR =   3000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel3:
-                            case CodecProfileLevel.HEVCHighTierLevel3:
-                                FR =    30; FS =   552960; BR =   6000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel31:
-                            case CodecProfileLevel.HEVCHighTierLevel31:
-                                FR = 33.75; FS =   983040; BR =  10000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel4:
-                                FR =    30; FS =  2228224; BR =  12000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel4:
-                                FR =    30; FS =  2228224; BR =  30000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel41:
-                                FR =    60; FS =  2228224; BR =  20000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel41:
-                                FR =    60; FS =  2228224; BR =  50000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel5:
-                                FR =    30; FS =  8912896; BR =  25000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel5:
-                                FR =    30; FS =  8912896; BR = 100000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel51:
-                                FR =    60; FS =  8912896; BR =  40000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel51:
-                                FR =    60; FS =  8912896; BR = 160000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel52:
-                                FR =   120; FS =  8912896; BR =  60000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel52:
-                                FR =   120; FS =  8912896; BR = 240000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel6:
-                                FR =    30; FS = 35651584; BR =  60000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel6:
-                                FR =    30; FS = 35651584; BR = 240000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel61:
-                                FR =    60; FS = 35651584; BR = 120000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel61:
-                                FR =    60; FS = 35651584; BR = 480000; break;
-                            case CodecProfileLevel.HEVCMainTierLevel62:
-                                FR =   120; FS = 35651584; BR = 240000; break;
-                            case CodecProfileLevel.HEVCHighTierLevel62:
-                                FR =   120; FS = 35651584; BR = 800000; break;
-                            default:
-                                Log.w(TAG, "Unrecognized level "
-                                        + profileLevel.level + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-                        switch (profileLevel.profile) {
-                            case CodecProfileLevel.HEVCProfileMain:
-                            case CodecProfileLevel.HEVCProfileMain10:
-                                break;
-                            default:
-                                Log.w(TAG, "Unrecognized profile "
-                                        + profileLevel.profile + " for " + mime);
-                                errors |= ERROR_UNRECOGNIZED;
-                        }
-
-                        /* DPB logic:
-                        if      (width * height <= FS / 4)    DPB = 16;
-                        else if (width * height <= FS / 2)    DPB = 12;
-                        else if (width * height <= FS * 0.75) DPB = 8;
-                        else                                  DPB = 6;
-                        */
-
-                        errors &= ~ERROR_NONE_SUPPORTED;
-                        maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond);
-                        maxBlocks = Math.max(FS, maxBlocks);
-                        maxBps = Math.max(BR * 1000, maxBps);
-                    }
-
-                    int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
-                    // CTBs are at least 8x8
-                    maxBlocks = Utils.divUp(maxBlocks, 8 * 8);
-                    maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, 8 * 8);
-                    maxLengthInBlocks = Utils.divUp(maxLengthInBlocks, 8);
-
-                    applyMacroBlockLimits(
-                            maxLengthInBlocks, maxLengthInBlocks,
-                            maxBlocks, maxBlocksPerSecond,
-                            8 /* blockWidth */, 8 /* blockHeight */,
-                            1 /* widthAlignment */, 1 /* heightAlignment */);
-                } else {
-                    Log.w(TAG, "Unsupported mime " + mime);
-                    // using minimal bitrate here.  should be overriden by
-                    // info from media_codecs.xml
-                    maxBps = 64000;
-                    errors |= ERROR_UNSUPPORTED;
-                }
-                mBitrateRange = Range.create(1, maxBps);
-                mParent.mError |= errors;
-            }
-        };
-
-        VideoCapabilities mVideoCaps;
-
         private boolean isVideo() {
             return mVideoCaps != null;
         }
@@ -1624,16 +393,28 @@
         /**
          * Returns the video capabilities or {@code null} if this is not a video codec.
          */
-        public final VideoCapabilities getVideoCapabilities() {
+        public VideoCapabilities getVideoCapabilities() {
             return mVideoCaps;
         }
 
+        /** @hide */
+        public CodecCapabilities dup() {
+            return new CodecCapabilities(
+                // clone writable arrays
+                Arrays.copyOf(profileLevels, profileLevels.length),
+                Arrays.copyOf(colorFormats, colorFormats.length),
+                isEncoder(),
+                mFlagsVerified,
+                mDefaultFormat,
+                mCapabilitiesInfo);
+        }
+
         /**
          * Retrieve the codec capabilities for a certain {@code mime type}, {@code
          * profile} and {@code level}.  If the type, or profile-level combination
          * is not understood by the framework, it returns null.
          */
-        public static final CodecCapabilities CreateFromProfileLevel(
+        public static CodecCapabilities CreateFromProfileLevel(
                 String mime, int profile, int level) {
             CodecProfileLevel pl = new CodecProfileLevel();
             pl.profile = profile;
@@ -1699,282 +480,1503 @@
                 // TODO restrict features by mFlagsVerified once all codecs reliably verify them
             }
         }
+    }
+
+    /**
+     * A class that supports querying the audio capabilities of a codec.
+     */
+    public static final class AudioCapabilities {
+        private static final String TAG = "AudioCapabilities";
+        private CodecCapabilities mParent;
+        private Range<Integer> mBitrateRange;
+
+        private int[] mSampleRates;
+        private Range<Integer>[] mSampleRateRanges;
+        private int mMaxInputChannelCount;
+
+        private static final int MAX_INPUT_CHANNEL_COUNT = 30;
 
         /**
-         * A class that supports querying the audio capabilities of a codec.
+         * Returns the range of supported bitrates in bits/second.
          */
-        public static final class AudioCapabilities extends BaseCapabilities {
-            private static final String TAG = "AudioCapabilities";
-
-            private int[] mSampleRates;
-            private Range<Integer>[] mSampleRateRanges;
-            private int mMaxInputChannelCount;
-
-            private static final int MAX_INPUT_CHANNEL_COUNT = 30;
-
-            /**
-             * Returns the array of supported sample rates if the codec
-             * supports only discrete values.  Otherwise, it returns
-             * {@code null}.  The array is sorted in ascending order.
-             */
-            public final int[] getSupportedSampleRates() {
-                return Arrays.copyOf(mSampleRates, mSampleRates.length);
-            }
-
-            /**
-             * Returns the array of supported sample rate ranges.  The
-             * array is sorted in ascending order, and the ranges are
-             * distinct.
-             */
-            public final Range<Integer>[] getSupportedSampleRateRanges() {
-                return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
-            }
-
-            /**
-             * Returns the maximum number of input channels supported.  The codec
-             * supports any number of channels between 1 and this maximum value.
-             */
-            public final int getMaxInputChannelCount() {
-                return mMaxInputChannelCount;
-            }
-
-            /* no public constructor */
-            private AudioCapabilities() { }
-
-            /** @hide */
-            public static AudioCapabilities create(
-                    MediaFormat info, CodecCapabilities parent) {
-                AudioCapabilities caps = new AudioCapabilities();
-                caps.init(info, parent);
-                return caps;
-            }
-
-            /** @hide */
-            public void init(MediaFormat info, CodecCapabilities parent) {
-                super.init(info, parent);
-                initWithPlatformLimits();
-                applyLevelLimits();
-                parseFromInfo(info);
-            }
-
-            private void initWithPlatformLimits() {
-                mMaxInputChannelCount = MAX_INPUT_CHANNEL_COUNT;
-                // mBitrateRange = Range.create(1, 320000);
-                mSampleRateRanges = new Range[] { Range.create(8000, 96000) };
-                mSampleRates = null;
-            }
-
-            private boolean supports(Integer sampleRate, Integer inputChannels) {
-                // channels and sample rates are checked orthogonally
-                if (inputChannels != null &&
-                        (inputChannels < 1 || inputChannels > mMaxInputChannelCount)) {
-                    return false;
-                }
-                if (sampleRate != null) {
-                    int ix = Utils.binarySearchDistinctRanges(
-                            mSampleRateRanges, sampleRate);
-                    if (ix < 0) {
-                        return false;
-                    }
-                }
-                return true;
-            }
-
-            /**
-             * Query whether the sample rate is supported by the codec.
-             */
-            public final boolean isSampleRateSupported(int sampleRate) {
-                return supports(sampleRate, null);
-            }
-
-            /** modifies rates */
-            private void limitSampleRates(int[] rates) {
-                Arrays.sort(rates);
-                ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>();
-                for (int rate: rates) {
-                    if (supports(rate, null /* channels */)) {
-                        ranges.add(Range.create(rate, rate));
-                    }
-                }
-                mSampleRateRanges = ranges.toArray(new Range[ranges.size()]);
-                createDiscreteSampleRates();
-            }
-
-            private void createDiscreteSampleRates() {
-                mSampleRates = new int[mSampleRateRanges.length];
-                for (int i = 0; i < mSampleRateRanges.length; i++) {
-                    mSampleRates[i] = mSampleRateRanges[i].getLower();
-                }
-            }
-
-            /** modifies rateRanges */
-            private void limitSampleRates(Range<Integer>[] rateRanges) {
-                sortDistinctRanges(rateRanges);
-                mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
-
-                // check if all values are discrete
-                for (Range<Integer> range: mSampleRateRanges) {
-                    if (!range.getLower().equals(range.getUpper())) {
-                        mSampleRates = null;
-                        return;
-                    }
-                }
-                createDiscreteSampleRates();
-            }
-
-            private void applyLevelLimits() {
-                int[] sampleRates = null;
-                Range<Integer> sampleRateRange = null, bitRates = null;
-                int maxChannels = 0;
-                String mime = mParent.getMime();
-
-                if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
-                    sampleRates = new int[] {
-                            8000, 11025, 12000,
-                            16000, 22050, 24000,
-                            32000, 44100, 48000 };
-                    bitRates = Range.create(8000, 320000);
-                    maxChannels = 2;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
-                    sampleRates = new int[] { 8000 };
-                    bitRates = Range.create(4750, 12200);
-                    maxChannels = 1;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) {
-                    sampleRates = new int[] { 16000 };
-                    bitRates = Range.create(6600, 23850);
-                    maxChannels = 1;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-                    sampleRates = new int[] {
-                            7350, 8000,
-                            11025, 12000, 16000,
-                            22050, 24000, 32000,
-                            44100, 48000, 64000,
-                            88200, 96000 };
-                    bitRates = Range.create(8000, 510000);
-                    maxChannels = 48;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) {
-                    bitRates = Range.create(32000, 500000);
-                    sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000, 192000 };
-                    maxChannels = 255;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) {
-                    bitRates = Range.create(6000, 510000);
-                    sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 };
-                    maxChannels = 255;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) {
-                    sampleRateRange = Range.create(1, 96000);
-                    bitRates = Range.create(1, 10000000);
-                    maxChannels = 8;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
-                    sampleRateRange = Range.create(1, 655350);
-                    // lossless codec, so bitrate is ignored
-                    maxChannels = 255;
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
-                        || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) {
-                    sampleRates = new int[] { 8000 };
-                    bitRates = Range.create(64000, 64000);
-                    // platform allows multiple channels for this format
-                } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
-                    sampleRates = new int[] { 8000 };
-                    bitRates = Range.create(13000, 13000);
-                    maxChannels = 1;
-                } else {
-                    Log.w(TAG, "Unsupported mime " + mime);
-                    mParent.mError |= ERROR_UNSUPPORTED;
-                }
-
-                // restrict ranges
-                if (sampleRates != null) {
-                    limitSampleRates(sampleRates);
-                } else if (sampleRateRange != null) {
-                    limitSampleRates(new Range[] { sampleRateRange });
-                }
-                applyLimits(maxChannels, bitRates);
-            }
-
-            private void applyLimits(int maxInputChannels, Range<Integer> bitRates) {
-                mMaxInputChannelCount = Range.create(1, mMaxInputChannelCount)
-                        .clamp(maxInputChannels);
-                if (bitRates != null) {
-                    mBitrateRange = mBitrateRange.intersect(bitRates);
-                }
-            }
-
-            private void parseFromInfo(MediaFormat info) {
-                int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
-                Range<Integer> bitRates = POSITIVE_INTEGERS;
-
-                if (info.containsKey("sample-rate-ranges")) {
-                    String[] rateStrings = info.getString("sample-rate-ranges").split(",");
-                    Range<Integer>[] rateRanges = new Range[rateStrings.length];
-                    for (int i = 0; i < rateStrings.length; i++) {
-                        rateRanges[i] = Utils.parseIntRange(rateStrings[i], null);
-                    }
-                    limitSampleRates(rateRanges);
-                }
-                if (info.containsKey("max-channel-count")) {
-                    maxInputChannels = Utils.parseIntSafely(
-                            info.getString("max-channel-count"), maxInputChannels);
-                }
-                if (info.containsKey("bitrate-range")) {
-                    bitRates = bitRates.intersect(
-                            Utils.parseIntRange(info.getString("bitrate"), bitRates));
-                }
-                applyLimits(maxInputChannels, bitRates);
-            }
-
-            /** @hide */
-            public void setDefaultFormat(MediaFormat format) {
-                // report settings that have only a single choice
-                if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
-                    format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
-                }
-                if (mMaxInputChannelCount == 1) {
-                    // mono-only format
-                    format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
-                }
-                if (mSampleRates != null && mSampleRates.length == 1) {
-                    format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]);
-                }
-            }
-
-            /** @hide */
-            public boolean supportsFormat(MediaFormat format) {
-                Map<String, Object> map = format.getMap();
-                Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
-                Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
-                if (!supports(sampleRate, channels)) {
-                    return false;
-                }
-
-                // nothing to do for:
-                // KEY_CHANNEL_MASK: codecs don't get this
-                // KEY_IS_ADTS:      required feature for all AAC decoders
-                return true;
-            }
-        };
-
-        AudioCapabilities mAudioCaps;
-        private boolean isAudio() {
-            return mAudioCaps != null;
+        public Range<Integer> getBitrateRange() {
+            return mBitrateRange;
         }
 
         /**
-         * Returns the audio capabilities or {@code null} if this is not an audio codec.
+         * Returns the array of supported sample rates if the codec
+         * supports only discrete values.  Otherwise, it returns
+         * {@code null}.  The array is sorted in ascending order.
          */
-        public final AudioCapabilities getAudioCapabilities() {
-            return mAudioCaps;
+        public int[] getSupportedSampleRates() {
+            return Arrays.copyOf(mSampleRates, mSampleRates.length);
+        }
+
+        /**
+         * Returns the array of supported sample rate ranges.  The
+         * array is sorted in ascending order, and the ranges are
+         * distinct.
+         */
+        public Range<Integer>[] getSupportedSampleRateRanges() {
+            return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
+        }
+
+        /**
+         * Returns the maximum number of input channels supported.  The codec
+         * supports any number of channels between 1 and this maximum value.
+         */
+        public int getMaxInputChannelCount() {
+            return mMaxInputChannelCount;
+        }
+
+        /* no public constructor */
+        private AudioCapabilities() { }
+
+        /** @hide */
+        public static AudioCapabilities create(
+                MediaFormat info, CodecCapabilities parent) {
+            AudioCapabilities caps = new AudioCapabilities();
+            caps.init(info, parent);
+            return caps;
         }
 
         /** @hide */
-        public CodecCapabilities dup() {
-            return new CodecCapabilities(
-                // clone writable arrays
-                Arrays.copyOf(profileLevels, profileLevels.length),
-                Arrays.copyOf(colorFormats, colorFormats.length),
-                isEncoder(),
-                mFlagsVerified,
-                mDefaultFormat,
-                mCapabilitiesInfo);
+        public void init(MediaFormat info, CodecCapabilities parent) {
+            mParent = parent;
+            initWithPlatformLimits();
+            applyLevelLimits();
+            parseFromInfo(info);
+        }
+
+        private void initWithPlatformLimits() {
+            mBitrateRange = Range.create(0, Integer.MAX_VALUE);
+            mMaxInputChannelCount = MAX_INPUT_CHANNEL_COUNT;
+            // mBitrateRange = Range.create(1, 320000);
+            mSampleRateRanges = new Range[] { Range.create(8000, 96000) };
+            mSampleRates = null;
+        }
+
+        private boolean supports(Integer sampleRate, Integer inputChannels) {
+            // channels and sample rates are checked orthogonally
+            if (inputChannels != null &&
+                    (inputChannels < 1 || inputChannels > mMaxInputChannelCount)) {
+                return false;
+            }
+            if (sampleRate != null) {
+                int ix = Utils.binarySearchDistinctRanges(
+                        mSampleRateRanges, sampleRate);
+                if (ix < 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /**
+         * Query whether the sample rate is supported by the codec.
+         */
+        public boolean isSampleRateSupported(int sampleRate) {
+            return supports(sampleRate, null);
+        }
+
+        /** modifies rates */
+        private void limitSampleRates(int[] rates) {
+            Arrays.sort(rates);
+            ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>();
+            for (int rate: rates) {
+                if (supports(rate, null /* channels */)) {
+                    ranges.add(Range.create(rate, rate));
+                }
+            }
+            mSampleRateRanges = ranges.toArray(new Range[ranges.size()]);
+            createDiscreteSampleRates();
+        }
+
+        private void createDiscreteSampleRates() {
+            mSampleRates = new int[mSampleRateRanges.length];
+            for (int i = 0; i < mSampleRateRanges.length; i++) {
+                mSampleRates[i] = mSampleRateRanges[i].getLower();
+            }
+        }
+
+        /** modifies rateRanges */
+        private void limitSampleRates(Range<Integer>[] rateRanges) {
+            sortDistinctRanges(rateRanges);
+            mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
+
+            // check if all values are discrete
+            for (Range<Integer> range: mSampleRateRanges) {
+                if (!range.getLower().equals(range.getUpper())) {
+                    mSampleRates = null;
+                    return;
+                }
+            }
+            createDiscreteSampleRates();
+        }
+
+        private void applyLevelLimits() {
+            int[] sampleRates = null;
+            Range<Integer> sampleRateRange = null, bitRates = null;
+            int maxChannels = 0;
+            String mime = mParent.getMimeType();
+
+            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
+                sampleRates = new int[] {
+                        8000, 11025, 12000,
+                        16000, 22050, 24000,
+                        32000, 44100, 48000 };
+                bitRates = Range.create(8000, 320000);
+                maxChannels = 2;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+                sampleRates = new int[] { 8000 };
+                bitRates = Range.create(4750, 12200);
+                maxChannels = 1;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) {
+                sampleRates = new int[] { 16000 };
+                bitRates = Range.create(6600, 23850);
+                maxChannels = 1;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+                sampleRates = new int[] {
+                        7350, 8000,
+                        11025, 12000, 16000,
+                        22050, 24000, 32000,
+                        44100, 48000, 64000,
+                        88200, 96000 };
+                bitRates = Range.create(8000, 510000);
+                maxChannels = 48;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) {
+                bitRates = Range.create(32000, 500000);
+                sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000, 192000 };
+                maxChannels = 255;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) {
+                bitRates = Range.create(6000, 510000);
+                sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 };
+                maxChannels = 255;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) {
+                sampleRateRange = Range.create(1, 96000);
+                bitRates = Range.create(1, 10000000);
+                maxChannels = 8;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+                sampleRateRange = Range.create(1, 655350);
+                // lossless codec, so bitrate is ignored
+                maxChannels = 255;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
+                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) {
+                sampleRates = new int[] { 8000 };
+                bitRates = Range.create(64000, 64000);
+                // platform allows multiple channels for this format
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
+                sampleRates = new int[] { 8000 };
+                bitRates = Range.create(13000, 13000);
+                maxChannels = 1;
+            } else {
+                Log.w(TAG, "Unsupported mime " + mime);
+                mParent.mError |= ERROR_UNSUPPORTED;
+            }
+
+            // restrict ranges
+            if (sampleRates != null) {
+                limitSampleRates(sampleRates);
+            } else if (sampleRateRange != null) {
+                limitSampleRates(new Range[] { sampleRateRange });
+            }
+            applyLimits(maxChannels, bitRates);
+        }
+
+        private void applyLimits(int maxInputChannels, Range<Integer> bitRates) {
+            mMaxInputChannelCount = Range.create(1, mMaxInputChannelCount)
+                    .clamp(maxInputChannels);
+            if (bitRates != null) {
+                mBitrateRange = mBitrateRange.intersect(bitRates);
+            }
+        }
+
+        private void parseFromInfo(MediaFormat info) {
+            int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
+            Range<Integer> bitRates = POSITIVE_INTEGERS;
+
+            if (info.containsKey("sample-rate-ranges")) {
+                String[] rateStrings = info.getString("sample-rate-ranges").split(",");
+                Range<Integer>[] rateRanges = new Range[rateStrings.length];
+                for (int i = 0; i < rateStrings.length; i++) {
+                    rateRanges[i] = Utils.parseIntRange(rateStrings[i], null);
+                }
+                limitSampleRates(rateRanges);
+            }
+            if (info.containsKey("max-channel-count")) {
+                maxInputChannels = Utils.parseIntSafely(
+                        info.getString("max-channel-count"), maxInputChannels);
+            }
+            if (info.containsKey("bitrate-range")) {
+                bitRates = bitRates.intersect(
+                        Utils.parseIntRange(info.getString("bitrate"), bitRates));
+            }
+            applyLimits(maxInputChannels, bitRates);
+        }
+
+        /** @hide */
+        public void setDefaultFormat(MediaFormat format) {
+            // report settings that have only a single choice
+            if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
+                format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
+            }
+            if (mMaxInputChannelCount == 1) {
+                // mono-only format
+                format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+            }
+            if (mSampleRates != null && mSampleRates.length == 1) {
+                format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]);
+            }
+        }
+
+        /** @hide */
+        public boolean supportsFormat(MediaFormat format) {
+            Map<String, Object> map = format.getMap();
+            Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
+            Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
+            if (!supports(sampleRate, channels)) {
+                return false;
+            }
+
+            // nothing to do for:
+            // KEY_CHANNEL_MASK: codecs don't get this
+            // KEY_IS_ADTS:      required feature for all AAC decoders
+            return true;
+        }
+    }
+
+    /**
+     * A class that supports querying the video capabilities of a codec.
+     */
+    public static final class VideoCapabilities {
+        private static final String TAG = "VideoCapabilities";
+        private CodecCapabilities mParent;
+        private Range<Integer> mBitrateRange;
+
+        private Range<Integer> mHeightRange;
+        private Range<Integer> mWidthRange;
+        private Range<Integer> mBlockCountRange;
+        private Range<Integer> mHorizontalBlockRange;
+        private Range<Integer> mVerticalBlockRange;
+        private Range<Rational> mAspectRatioRange;
+        private Range<Rational> mBlockAspectRatioRange;
+        private Range<Long> mBlocksPerSecondRange;
+        private Range<Integer> mFrameRateRange;
+
+        private int mBlockWidth;
+        private int mBlockHeight;
+        private int mWidthAlignment;
+        private int mHeightAlignment;
+        private int mSmallerDimensionUpperLimit;
+
+        /**
+         * Returns the range of supported bitrates in bits/second.
+         */
+        public Range<Integer> getBitrateRange() {
+            return mBitrateRange;
+        }
+
+        /**
+         * Returns the range of supported video widths.
+         */
+        public Range<Integer> getSupportedWidths() {
+            return mWidthRange;
+        }
+
+        /**
+         * Returns the range of supported video heights.
+         */
+        public Range<Integer> getSupportedHeights() {
+            return mHeightRange;
+        }
+
+        /**
+         * Returns the alignment requirement for video width (in pixels).
+         *
+         * This is a power-of-2 value that video width must be a
+         * multiple of.
+         */
+        public int getWidthAlignment() {
+            return mWidthAlignment;
+        }
+
+        /**
+         * Returns the alignment requirement for video height (in pixels).
+         *
+         * This is a power-of-2 value that video height must be a
+         * multiple of.
+         */
+        public int getHeightAlignment() {
+            return mHeightAlignment;
+        }
+
+        /**
+         * Return the upper limit on the smaller dimension of width or height.
+         * <p></p>
+         * Some codecs have a limit on the smaller dimension, whether it be
+         * the width or the height.  E.g. a codec may only be able to handle
+         * up to 1920x1080 both in landscape and portrait mode (1080x1920).
+         * In this case the maximum width and height are both 1920, but the
+         * smaller dimension limit will be 1080. For other codecs, this is
+         * {@code Math.min(getSupportedWidths().getUpper(),
+         * getSupportedHeights().getUpper())}.
+         *
+         * @hide
+         */
+        public int getSmallerDimensionUpperLimit() {
+            return mSmallerDimensionUpperLimit;
+        }
+
+        /**
+         * Returns the range of supported frame rates.
+         * <p>
+         * This is not a performance indicator.  Rather, it expresses the
+         * limits specified in the coding standard, based on the complexities
+         * of encoding material for later playback at a certain frame rate,
+         * or the decoding of such material in non-realtime.
+         */
+        public Range<Integer> getSupportedFrameRates() {
+            return mFrameRateRange;
+        }
+
+        /**
+         * Returns the range of supported video widths for a video height.
+         * @param height the height of the video
+         */
+        public Range<Integer> getSupportedWidthsFor(int height) {
+            try {
+                Range<Integer> range = mWidthRange;
+                if (!mHeightRange.contains(height)
+                        || (height % mHeightAlignment) != 0) {
+                    throw new IllegalArgumentException("unsupported height");
+                }
+                final int heightInBlocks = Utils.divUp(height, mBlockHeight);
+
+                // constrain by block count and by block aspect ratio
+                final int minWidthInBlocks = Math.max(
+                        Utils.divUp(mBlockCountRange.getLower(), heightInBlocks),
+                        (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue()
+                                * heightInBlocks));
+                final int maxWidthInBlocks = Math.min(
+                        mBlockCountRange.getUpper() / heightInBlocks,
+                        (int)(mBlockAspectRatioRange.getUpper().doubleValue()
+                                * heightInBlocks));
+                range = range.intersect(
+                        (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment,
+                        maxWidthInBlocks * mBlockWidth);
+
+                // constrain by smaller dimension limit
+                if (height > mSmallerDimensionUpperLimit) {
+                    range = range.intersect(1, mSmallerDimensionUpperLimit);
+                }
+
+                // constrain by aspect ratio
+                range = range.intersect(
+                        (int)Math.ceil(mAspectRatioRange.getLower().doubleValue()
+                                * height),
+                        (int)(mAspectRatioRange.getUpper().doubleValue() * height));
+                return range;
+            } catch (IllegalArgumentException e) {
+                // should not be here
+                Log.w(TAG, "could not get supported widths for " + height , e);
+                throw new IllegalArgumentException("unsupported height");
+            }
+        }
+
+        /**
+         * Returns the range of supported video heights for a video width
+         * @param width the width of the video
+         */
+        public Range<Integer> getSupportedHeightsFor(int width) {
+            try {
+                Range<Integer> range = mHeightRange;
+                if (!mWidthRange.contains(width)
+                        || (width % mWidthAlignment) != 0) {
+                    throw new IllegalArgumentException("unsupported width");
+                }
+                final int widthInBlocks = Utils.divUp(width, mBlockWidth);
+
+                // constrain by block count and by block aspect ratio
+                final int minHeightInBlocks = Math.max(
+                        Utils.divUp(mBlockCountRange.getLower(), widthInBlocks),
+                        (int)Math.ceil(widthInBlocks /
+                                mBlockAspectRatioRange.getUpper().doubleValue()));
+                final int maxHeightInBlocks = Math.min(
+                        mBlockCountRange.getUpper() / widthInBlocks,
+                        (int)(widthInBlocks /
+                                mBlockAspectRatioRange.getLower().doubleValue()));
+                range = range.intersect(
+                        (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment,
+                        maxHeightInBlocks * mBlockHeight);
+
+                // constrain by smaller dimension limit
+                if (width > mSmallerDimensionUpperLimit) {
+                    range = range.intersect(1, mSmallerDimensionUpperLimit);
+                }
+
+                // constrain by aspect ratio
+                range = range.intersect(
+                        (int)Math.ceil(width /
+                                mAspectRatioRange.getUpper().doubleValue()),
+                        (int)(width / mAspectRatioRange.getLower().doubleValue()));
+                return range;
+            } catch (IllegalArgumentException e) {
+                // should not be here
+                Log.w(TAG, "could not get supported heights for " + width , e);
+                throw new IllegalArgumentException("unsupported width");
+            }
+        }
+
+        /**
+         * Returns the range of supported video frame rates for a video size.
+         * <p>
+         * This is not a performance indicator.  Rather, it expresses the limits specified in
+         * the coding standard, based on the complexities of encoding material of a given
+         * size for later playback at a certain frame rate, or the decoding of such material
+         * in non-realtime.
+
+         * @param width the width of the video
+         * @param height the height of the video
+         */
+        public Range<Double> getSupportedFrameRatesFor(int width, int height) {
+            Range<Integer> range = mHeightRange;
+            if (!supports(width, height, null)) {
+                throw new IllegalArgumentException("unsupported size");
+            }
+            final int blockCount =
+                Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
+
+            return Range.create(
+                    Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount,
+                            (double) mFrameRateRange.getLower()),
+                    Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount,
+                            (double) mFrameRateRange.getUpper()));
+        }
+
+        /**
+         * Returns whether a given video size ({@code width} and
+         * {@code height}) and {@code frameRate} combination is supported.
+         */
+        public boolean areSizeAndRateSupported(
+                int width, int height, double frameRate) {
+            return supports(width, height, frameRate);
+        }
+
+        /**
+         * Returns whether a given video size ({@code width} and
+         * {@code height}) is supported.
+         */
+        public boolean isSizeSupported(int width, int height) {
+            return supports(width, height, null);
+        }
+
+        private boolean supports(
+                Integer width, Integer height, Double rate) {
+            boolean ok = true;
+
+            if (ok && width != null) {
+                ok = mWidthRange.contains(width)
+                        && (width % mWidthAlignment == 0);
+            }
+            if (ok && height != null) {
+                ok = mHeightRange.contains(height)
+                        && (height % mHeightAlignment == 0);
+            }
+            if (ok && rate != null) {
+                ok = mFrameRateRange.contains(Utils.intRangeFor(rate));
+            }
+            if (ok && height != null && width != null) {
+                ok = Math.min(height, width) <= mSmallerDimensionUpperLimit;
+
+                final int widthInBlocks = Utils.divUp(width, mBlockWidth);
+                final int heightInBlocks = Utils.divUp(height, mBlockHeight);
+                final int blockCount = widthInBlocks * heightInBlocks;
+                ok = ok && mBlockCountRange.contains(blockCount)
+                        && mBlockAspectRatioRange.contains(
+                                new Rational(widthInBlocks, heightInBlocks))
+                        && mAspectRatioRange.contains(new Rational(width, height));
+                if (ok && rate != null) {
+                    double blocksPerSec = blockCount * rate;
+                    ok = mBlocksPerSecondRange.contains(
+                            Utils.longRangeFor(blocksPerSec));
+                }
+            }
+            return ok;
+        }
+
+        /**
+         * @hide
+         * @throws java.lang.ClassCastException */
+        public boolean supportsFormat(MediaFormat format) {
+            final Map<String, Object> map = format.getMap();
+            Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH);
+            Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
+            Double rate = (Double)map.get(MediaFormat.KEY_FRAME_RATE);
+
+            // we ignore color-format for now as it is not reliably reported by codec
+
+            return supports(width, height, rate);
+        }
+
+        /* no public constructor */
+        private VideoCapabilities() { }
+
+        /** @hide */
+        public static VideoCapabilities create(
+                MediaFormat info, CodecCapabilities parent) {
+            VideoCapabilities caps = new VideoCapabilities();
+            caps.init(info, parent);
+            return caps;
+        }
+
+        /** @hide */
+        public void init(MediaFormat info, CodecCapabilities parent) {
+            mParent = parent;
+            initWithPlatformLimits();
+            applyLevelLimits();
+            parseFromInfo(info);
+            updateLimits();
+        }
+
+        /** @hide */
+        public Size getBlockSize() {
+            return new Size(mBlockWidth, mBlockHeight);
+        }
+
+        /** @hide */
+        public Range<Integer> getBlockCountRange() {
+            return mBlockCountRange;
+        }
+
+        /** @hide */
+        public Range<Long> getBlocksPerSecondRange() {
+            return mBlocksPerSecondRange;
+        }
+
+        /** @hide */
+        public Range<Rational> getAspectRatioRange(boolean blocks) {
+            return blocks ? mBlockAspectRatioRange : mAspectRatioRange;
+        }
+
+        private void initWithPlatformLimits() {
+            mBitrateRange = Range.create(0, Integer.MAX_VALUE);
+
+            mWidthRange  = SIZE_RANGE;
+            mHeightRange = SIZE_RANGE;
+            mFrameRateRange = FRAME_RATE_RANGE;
+
+            mHorizontalBlockRange = SIZE_RANGE;
+            mVerticalBlockRange   = SIZE_RANGE;
+
+            // full positive ranges are supported as these get calculated
+            mBlockCountRange      = POSITIVE_INTEGERS;
+            mBlocksPerSecondRange = POSITIVE_LONGS;
+
+            mBlockAspectRatioRange = POSITIVE_RATIONALS;
+            mAspectRatioRange      = POSITIVE_RATIONALS;
+
+            // YUV 4:2:0 requires 2:2 alignment
+            mWidthAlignment = 2;
+            mHeightAlignment = 2;
+            mBlockWidth = 2;
+            mBlockHeight = 2;
+            mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
+        }
+
+        private void parseFromInfo(MediaFormat info) {
+            final Map<String, Object> map = info.getMap();
+            Size blockSize = new Size(mBlockWidth, mBlockHeight);
+            Size alignment = new Size(mWidthAlignment, mHeightAlignment);
+            Range<Integer> counts = null, widths = null, heights = null;
+            Range<Integer> frameRates = null;
+            Range<Long> blockRates = null;
+            Range<Rational> ratios = null, blockRatios = null;
+
+            blockSize = Utils.parseSize(map.get("block-size"), blockSize);
+            alignment = Utils.parseSize(map.get("alignment"), alignment);
+            counts = Utils.parseIntRange(map.get("block-count-range"), null);
+            blockRates =
+                Utils.parseLongRange(map.get("blocks-per-second-range"), null);
+            {
+                Object o = map.get("size-range");
+                Pair<Size, Size> sizeRange = Utils.parseSizeRange(o);
+                if (sizeRange != null) {
+                    try {
+                        widths = Range.create(
+                                sizeRange.first.getWidth(),
+                                sizeRange.second.getWidth());
+                        heights = Range.create(
+                                sizeRange.first.getHeight(),
+                                sizeRange.second.getHeight());
+                    } catch (IllegalArgumentException e) {
+                        Log.w(TAG, "could not parse size range '" + o + "'");
+                        widths = null;
+                        heights = null;
+                    }
+                }
+            }
+            // for now this just means using the smaller max size as 2nd
+            // upper limit.
+            // for now we are keeping the profile specific "width/height
+            // in macroblocks" limits.
+            if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) {
+                if (widths != null) {
+                    mSmallerDimensionUpperLimit =
+                        Math.min(widths.getUpper(), heights.getUpper());
+                    widths = heights = widths.extend(heights);
+                } else {
+                    Log.w(TAG, "feature can-swap-width-height is best used with size-range");
+                    mSmallerDimensionUpperLimit =
+                        Math.min(mWidthRange.getUpper(), mHeightRange.getUpper());
+                    mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
+                }
+            }
+
+            ratios = Utils.parseRationalRange(
+                    map.get("block-aspect-ratio-range"), null);
+            blockRatios = Utils.parseRationalRange(
+                    map.get("pixel-aspect-ratio-range"), null);
+            frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null);
+            if (frameRates != null) {
+                try {
+                    frameRates = frameRates.intersect(FRAME_RATE_RANGE);
+                } catch (IllegalArgumentException e) {
+                    Log.w(TAG, "frame rate range (" + frameRates
+                            + ") is out of limits: " + FRAME_RATE_RANGE);
+                    frameRates = null;
+                }
+            }
+
+            checkPowerOfTwo(
+                    blockSize.getWidth(), "block-size width must be power of two");
+            checkPowerOfTwo(
+                    blockSize.getHeight(), "block-size height must be power of two");
+
+            checkPowerOfTwo(
+                    alignment.getWidth(), "alignment width must be power of two");
+            checkPowerOfTwo(
+                    alignment.getHeight(), "alignment height must be power of two");
+
+            // update block-size and alignment
+            applyMacroBlockLimits(
+                    Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
+                    Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(),
+                    alignment.getWidth(), alignment.getHeight());
+
+            if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
+                // codec supports profiles that we don't know.
+                // Use supplied values clipped to platform limits
+                if (widths != null) {
+                    mWidthRange = SIZE_RANGE.intersect(widths);
+                }
+                if (heights != null) {
+                    mHeightRange = SIZE_RANGE.intersect(heights);
+                }
+                if (counts != null) {
+                    mBlockCountRange = POSITIVE_INTEGERS.intersect(
+                            Utils.factorRange(counts, mBlockWidth * mBlockHeight
+                                    / blockSize.getWidth() / blockSize.getHeight()));
+                }
+                if (blockRates != null) {
+                    mBlocksPerSecondRange = POSITIVE_LONGS.intersect(
+                            Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
+                                    / blockSize.getWidth() / blockSize.getHeight()));
+                }
+                if (blockRatios != null) {
+                    mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
+                            Utils.scaleRange(blockRatios,
+                                    mBlockHeight / blockSize.getHeight(),
+                                    mBlockWidth / blockSize.getWidth()));
+                }
+                if (ratios != null) {
+                    mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios);
+                }
+                if (frameRates != null) {
+                    mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates);
+                }
+            } else {
+                // no unsupported profile/levels, so restrict values to known limits
+                if (widths != null) {
+                    mWidthRange = mWidthRange.intersect(widths);
+                }
+                if (heights != null) {
+                    mHeightRange = mHeightRange.intersect(heights);
+                }
+                if (counts != null) {
+                    mBlockCountRange = mBlockCountRange.intersect(
+                            Utils.factorRange(counts, mBlockWidth * mBlockHeight
+                                    / blockSize.getWidth() / blockSize.getHeight()));
+                }
+                if (blockRates != null) {
+                    mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
+                            Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
+                                    / blockSize.getWidth() / blockSize.getHeight()));
+                }
+                if (blockRatios != null) {
+                    mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
+                            Utils.scaleRange(blockRatios,
+                                    mBlockHeight / blockSize.getHeight(),
+                                    mBlockWidth / blockSize.getWidth()));
+                }
+                if (ratios != null) {
+                    mAspectRatioRange = mAspectRatioRange.intersect(ratios);
+                }
+                if (frameRates != null) {
+                    mFrameRateRange = mFrameRateRange.intersect(frameRates);
+                }
+            }
+            updateLimits();
+        }
+
+        private void applyBlockLimits(
+                int blockWidth, int blockHeight,
+                Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) {
+            checkPowerOfTwo(blockWidth, "blockWidth must be a power of two");
+            checkPowerOfTwo(blockHeight, "blockHeight must be a power of two");
+
+            final int newBlockWidth = Math.max(blockWidth, mBlockWidth);
+            final int newBlockHeight = Math.max(blockHeight, mBlockHeight);
+
+            // factor will always be a power-of-2
+            int factor =
+                newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight;
+            if (factor != 1) {
+                mBlockCountRange = Utils.factorRange(mBlockCountRange, factor);
+                mBlocksPerSecondRange = Utils.factorRange(
+                        mBlocksPerSecondRange, factor);
+                mBlockAspectRatioRange = Utils.scaleRange(
+                        mBlockAspectRatioRange,
+                        newBlockHeight / mBlockHeight,
+                        newBlockWidth / mBlockWidth);
+                mHorizontalBlockRange = Utils.factorRange(
+                        mHorizontalBlockRange, newBlockWidth / mBlockWidth);
+                mVerticalBlockRange = Utils.factorRange(
+                        mVerticalBlockRange, newBlockHeight / mBlockHeight);
+            }
+            factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight;
+            if (factor != 1) {
+                counts = Utils.factorRange(counts, factor);
+                rates = Utils.factorRange(rates, factor);
+                ratios = Utils.scaleRange(
+                        ratios, newBlockHeight / blockHeight,
+                        newBlockWidth / blockWidth);
+            }
+            mBlockCountRange = mBlockCountRange.intersect(counts);
+            mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates);
+            mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios);
+            mBlockWidth = newBlockWidth;
+            mBlockHeight = newBlockHeight;
+        }
+
+        private void applyAlignment(int widthAlignment, int heightAlignment) {
+            checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two");
+            checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two");
+
+            if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) {
+                // maintain assumption that 0 < alignment <= block-size
+                applyBlockLimits(
+                        Math.max(widthAlignment, mBlockWidth),
+                        Math.max(heightAlignment, mBlockHeight),
+                        POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS);
+            }
+
+            mWidthAlignment = Math.max(widthAlignment, mWidthAlignment);
+            mHeightAlignment = Math.max(heightAlignment, mHeightAlignment);
+
+            mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment);
+            mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment);
+        }
+
+        private void updateLimits() {
+            // pixels -> blocks <- counts
+            mHorizontalBlockRange = mHorizontalBlockRange.intersect(
+                    Utils.factorRange(mWidthRange, mBlockWidth));
+            mHorizontalBlockRange = mHorizontalBlockRange.intersect(
+                    Range.create(
+                            mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(),
+                            mBlockCountRange.getUpper() / mVerticalBlockRange.getLower()));
+            mVerticalBlockRange = mVerticalBlockRange.intersect(
+                    Utils.factorRange(mHeightRange, mBlockHeight));
+            mVerticalBlockRange = mVerticalBlockRange.intersect(
+                    Range.create(
+                            mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(),
+                            mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower()));
+            mBlockCountRange = mBlockCountRange.intersect(
+                    Range.create(
+                            mHorizontalBlockRange.getLower()
+                                    * mVerticalBlockRange.getLower(),
+                            mHorizontalBlockRange.getUpper()
+                                    * mVerticalBlockRange.getUpper()));
+            mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
+                    new Rational(
+                            mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()),
+                    new Rational(
+                            mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower()));
+
+            // blocks -> pixels
+            mWidthRange = mWidthRange.intersect(
+                    (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment,
+                    mHorizontalBlockRange.getUpper() * mBlockWidth);
+            mHeightRange = mHeightRange.intersect(
+                    (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment,
+                    mVerticalBlockRange.getUpper() * mBlockHeight);
+            mAspectRatioRange = mAspectRatioRange.intersect(
+                    new Rational(mWidthRange.getLower(), mHeightRange.getUpper()),
+                    new Rational(mWidthRange.getUpper(), mHeightRange.getLower()));
+
+            mSmallerDimensionUpperLimit = Math.min(
+                    mSmallerDimensionUpperLimit,
+                    Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()));
+
+            // blocks -> rate
+            mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
+                    mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(),
+                    mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper());
+            mFrameRateRange = mFrameRateRange.intersect(
+                    (int)(mBlocksPerSecondRange.getLower()
+                            / mBlockCountRange.getUpper()),
+                    (int)(mBlocksPerSecondRange.getUpper()
+                            / (double)mBlockCountRange.getLower()));
+        }
+
+        private void applyMacroBlockLimits(
+                int maxHorizontalBlocks, int maxVerticalBlocks,
+                int maxBlocks, long maxBlocksPerSecond,
+                int blockWidth, int blockHeight,
+                int widthAlignment, int heightAlignment) {
+            applyAlignment(widthAlignment, heightAlignment);
+            applyBlockLimits(
+                    blockWidth, blockHeight, Range.create(1, maxBlocks),
+                    Range.create(1L, maxBlocksPerSecond),
+                    Range.create(
+                            new Rational(1, maxVerticalBlocks),
+                            new Rational(maxHorizontalBlocks, 1)));
+            mHorizontalBlockRange =
+                    mHorizontalBlockRange.intersect(
+                            1, maxHorizontalBlocks / (mBlockWidth / blockWidth));
+            mVerticalBlockRange =
+                    mVerticalBlockRange.intersect(
+                            1, maxVerticalBlocks / (mBlockHeight / blockHeight));
+        }
+
+        private void applyLevelLimits() {
+            int maxBlocksPerSecond = 0;
+            int maxBlocks = 0;
+            int maxBps = 0;
+            int maxDPBBlocks = 0;
+
+            int errors = ERROR_NONE_SUPPORTED;
+            CodecProfileLevel[] profileLevels = mParent.profileLevels;
+            String mime = mParent.getMimeType();
+
+            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+                maxBlocks = 99;
+                maxBlocksPerSecond = 1485;
+                maxBps = 64000;
+                maxDPBBlocks = 396;
+                for (CodecProfileLevel profileLevel: profileLevels) {
+                    int MBPS = 0, FS = 0, BR = 0, DPB = 0;
+                    boolean supported = true;
+                    switch (profileLevel.level) {
+                        case CodecProfileLevel.AVCLevel1:
+                            MBPS =    1485; FS =    99; BR =     64; DPB =    396; break;
+                        case CodecProfileLevel.AVCLevel1b:
+                            MBPS =    1485; FS =    99; BR =    128; DPB =    396; break;
+                        case CodecProfileLevel.AVCLevel11:
+                            MBPS =    3000; FS =   396; BR =    192; DPB =    900; break;
+                        case CodecProfileLevel.AVCLevel12:
+                            MBPS =    6000; FS =   396; BR =    384; DPB =   2376; break;
+                        case CodecProfileLevel.AVCLevel13:
+                            MBPS =   11880; FS =   396; BR =    768; DPB =   2376; break;
+                        case CodecProfileLevel.AVCLevel2:
+                            MBPS =   11880; FS =   396; BR =   2000; DPB =   2376; break;
+                        case CodecProfileLevel.AVCLevel21:
+                            MBPS =   19800; FS =   792; BR =   4000; DPB =   4752; break;
+                        case CodecProfileLevel.AVCLevel22:
+                            MBPS =   20250; FS =  1620; BR =   4000; DPB =   8100; break;
+                        case CodecProfileLevel.AVCLevel3:
+                            MBPS =   40500; FS =  1620; BR =  10000; DPB =   8100; break;
+                        case CodecProfileLevel.AVCLevel31:
+                            MBPS =  108000; FS =  3600; BR =  14000; DPB =  18000; break;
+                        case CodecProfileLevel.AVCLevel32:
+                            MBPS =  216000; FS =  5120; BR =  20000; DPB =  20480; break;
+                        case CodecProfileLevel.AVCLevel4:
+                            MBPS =  245760; FS =  8192; BR =  20000; DPB =  32768; break;
+                        case CodecProfileLevel.AVCLevel41:
+                            MBPS =  245760; FS =  8192; BR =  50000; DPB =  32768; break;
+                        case CodecProfileLevel.AVCLevel42:
+                            MBPS =  522240; FS =  8704; BR =  50000; DPB =  34816; break;
+                        case CodecProfileLevel.AVCLevel5:
+                            MBPS =  589824; FS = 22080; BR = 135000; DPB = 110400; break;
+                        case CodecProfileLevel.AVCLevel51:
+                            MBPS =  983040; FS = 36864; BR = 240000; DPB = 184320; break;
+                        case CodecProfileLevel.AVCLevel52:
+                            MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
+                        default:
+                            Log.w(TAG, "Unrecognized level "
+                                    + profileLevel.level + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    switch (profileLevel.profile) {
+                        case CodecProfileLevel.AVCProfileHigh:
+                            BR *= 1250; break;
+                        case CodecProfileLevel.AVCProfileHigh10:
+                            BR *= 3000; break;
+                        case CodecProfileLevel.AVCProfileExtended:
+                        case CodecProfileLevel.AVCProfileHigh422:
+                        case CodecProfileLevel.AVCProfileHigh444:
+                            Log.w(TAG, "Unsupported profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNSUPPORTED;
+                            supported = false;
+                            // fall through - treat as base profile
+                        case CodecProfileLevel.AVCProfileBaseline:
+                        case CodecProfileLevel.AVCProfileMain:
+                            BR *= 1000; break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                            BR *= 1000;
+                    }
+                    if (supported) {
+                        errors &= ~ERROR_NONE_SUPPORTED;
+                    }
+                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
+                    maxBlocks = Math.max(FS, maxBlocks);
+                    maxBps = Math.max(BR, maxBps);
+                    maxDPBBlocks = Math.max(maxDPBBlocks, DPB);
+                }
+
+                int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
+                applyMacroBlockLimits(
+                        maxLengthInBlocks, maxLengthInBlocks,
+                        maxBlocks, maxBlocksPerSecond,
+                        16 /* blockWidth */, 16 /* blockHeight */,
+                        1 /* widthAlignment */, 1 /* heightAlignment */);
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
+                int maxWidth = 11, maxHeight = 9, maxRate = 15;
+                maxBlocks = 99;
+                maxBlocksPerSecond = 1485;
+                maxBps = 64000;
+                for (CodecProfileLevel profileLevel: profileLevels) {
+                    int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
+                    boolean supported = true;
+                    switch (profileLevel.profile) {
+                        case CodecProfileLevel.MPEG4ProfileSimple:
+                            switch (profileLevel.level) {
+                                case CodecProfileLevel.MPEG4Level0:
+                                    FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
+                                case CodecProfileLevel.MPEG4Level1:
+                                    FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
+                                case CodecProfileLevel.MPEG4Level0b:
+                                    FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR = 128; break;
+                                case CodecProfileLevel.MPEG4Level2:
+                                    FR = 30; W = 22; H = 18; MBPS =  5940; FS = 396; BR = 128; break;
+                                case CodecProfileLevel.MPEG4Level3:
+                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break;
+                                case CodecProfileLevel.MPEG4Level4:
+                                case CodecProfileLevel.MPEG4Level4a:
+                                case CodecProfileLevel.MPEG4Level5:
+                                    // While MPEG4 SP does not have level 4 or 5, some vendors
+                                    // report it. Use the same limits as level 3, but mark as
+                                    // unsupported.
+                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384;
+                                    supported = false;
+                                    break;
+                                default:
+                                    Log.w(TAG, "Unrecognized profile/level "
+                                            + profileLevel.profile + "/"
+                                            + profileLevel.level + " for " + mime);
+                                    errors |= ERROR_UNRECOGNIZED;
+                            }
+                            break;
+                        case CodecProfileLevel.MPEG4ProfileAdvancedSimple:
+                            switch (profileLevel.level) {
+                                case CodecProfileLevel.MPEG4Level0:
+                                case CodecProfileLevel.MPEG4Level1:
+                                    FR = 30; W = 11; H =  9; MBPS =  2970; FS =   99; BR =  128; break;
+                                case CodecProfileLevel.MPEG4Level2:
+                                    FR = 30; W = 22; H = 18; MBPS =  5940; FS =  396; BR =  384; break;
+                                case CodecProfileLevel.MPEG4Level3:
+                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR =  768; break;
+                                // case CodecProfileLevel.MPEG4Level3b:
+                                // TODO: MPEG4 level 3b is not defined in OMX
+                                //  MBPS = 11880; FS =  396; BR = 1500; break;
+                                case CodecProfileLevel.MPEG4Level4:
+                                case CodecProfileLevel.MPEG4Level4a:
+                                    // TODO: MPEG4 level 4a is not defined in spec
+                                    FR = 30; W = 44; H = 36; MBPS = 23760; FS =  792; BR = 3000; break;
+                                case CodecProfileLevel.MPEG4Level5:
+                                    FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break;
+                                default:
+                                    Log.w(TAG, "Unrecognized profile/level "
+                                            + profileLevel.profile + "/"
+                                            + profileLevel.level + " for " + mime);
+                                    errors |= ERROR_UNRECOGNIZED;
+                            }
+                            break;
+                        case CodecProfileLevel.MPEG4ProfileMain:             // 2-4
+                        case CodecProfileLevel.MPEG4ProfileNbit:             // 2
+                        case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4
+                        case CodecProfileLevel.MPEG4ProfileCoreScalable:     // 1-3
+                        case CodecProfileLevel.MPEG4ProfileAdvancedCoding:   // 1-4
+                        case CodecProfileLevel.MPEG4ProfileCore:             // 1-2
+                        case CodecProfileLevel.MPEG4ProfileAdvancedCore:     // 1-4
+                        case CodecProfileLevel.MPEG4ProfileSimpleScalable:   // 0-2
+                        case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3
+                        case CodecProfileLevel.MPEG4ProfileHybrid:           // 1-2
+                        case CodecProfileLevel.MPEG4ProfileBasicAnimated:    // 1-2
+                        case CodecProfileLevel.MPEG4ProfileScalableTexture:  // 1
+                        case CodecProfileLevel.MPEG4ProfileSimpleFace:       // 1-2
+                        case CodecProfileLevel.MPEG4ProfileSimpleFBA:        // 1-2
+                            Log.i(TAG, "Unsupported profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNSUPPORTED;
+                            supported = false;
+                            break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    if (supported) {
+                        errors &= ~ERROR_NONE_SUPPORTED;
+                    }
+                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
+                    maxBlocks = Math.max(FS, maxBlocks);
+                    maxBps = Math.max(BR * 1000, maxBps);
+                    maxWidth = Math.max(W, maxWidth);
+                    maxHeight = Math.max(H, maxHeight);
+                    maxRate = Math.max(FR, maxRate);
+                }
+                applyMacroBlockLimits(maxWidth, maxHeight,
+                        maxBlocks, maxBlocksPerSecond,
+                        16 /* blockWidth */, 16 /* blockHeight */,
+                        1 /* widthAlignment */, 1 /* heightAlignment */);
+                mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
+                int maxWidth = 11, maxHeight = 9, maxRate = 15;
+                maxBlocks = 99;
+                maxBlocksPerSecond = 1485;
+                maxBps = 64000;
+                for (CodecProfileLevel profileLevel: profileLevels) {
+                    int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0;
+                    switch (profileLevel.level) {
+                        case CodecProfileLevel.H263Level10:
+                            FR = 15; W = 11; H =  9; BR =   1; MBPS =  W * H * FR; break;
+                        case CodecProfileLevel.H263Level20:
+                            // only supports CIF, 0..QCIF
+                            FR = 30; W = 22; H = 18; BR =   2; MBPS =  W * H * FR; break;
+                        case CodecProfileLevel.H263Level30:
+                            // only supports CIF, 0..QCIF
+                            FR = 30; W = 22; H = 18; BR =   6; MBPS =  W * H * FR; break;
+                        case CodecProfileLevel.H263Level40:
+                            // only supports CIF, 0..QCIF
+                            FR = 30; W = 22; H = 18; BR =  32; MBPS =  W * H * FR; break;
+                        case CodecProfileLevel.H263Level45:
+                            // only implies level 10 support
+                            FR = 30; W = 11; H =  9; BR =   2; MBPS =  W * H * FR; break;
+                        case CodecProfileLevel.H263Level50:
+                            // only supports 50fps for H > 15
+                            FR = 60; W = 22; H = 18; BR =  64; MBPS =  W * H * 50; break;
+                        case CodecProfileLevel.H263Level60:
+                            // only supports 50fps for H > 15
+                            FR = 60; W = 45; H = 18; BR = 128; MBPS =  W * H * 50; break;
+                        case CodecProfileLevel.H263Level70:
+                            // only supports 50fps for H > 30
+                            FR = 60; W = 45; H = 36; BR = 256; MBPS =  W * H * 50; break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile
+                                    + "/" + profileLevel.level + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    switch (profileLevel.profile) {
+                        case CodecProfileLevel.H263ProfileBackwardCompatible:
+                        case CodecProfileLevel.H263ProfileBaseline:
+                        case CodecProfileLevel.H263ProfileH320Coding:
+                        case CodecProfileLevel.H263ProfileHighCompression:
+                        case CodecProfileLevel.H263ProfileHighLatency:
+                        case CodecProfileLevel.H263ProfileInterlace:
+                        case CodecProfileLevel.H263ProfileInternet:
+                        case CodecProfileLevel.H263ProfileISWV2:
+                        case CodecProfileLevel.H263ProfileISWV3:
+                            break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    errors &= ~ERROR_NONE_SUPPORTED;
+                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
+                    maxBlocks = Math.max(W * H, maxBlocks);
+                    maxBps = Math.max(BR * 64000, maxBps);
+                    maxWidth = Math.max(W, maxWidth);
+                    maxHeight = Math.max(H, maxHeight);
+                    maxRate = Math.max(FR, maxRate);
+                }
+                applyMacroBlockLimits(maxWidth, maxHeight,
+                        maxBlocks, maxBlocksPerSecond,
+                        16 /* blockWidth */, 16 /* blockHeight */,
+                        1 /* widthAlignment */, 1 /* heightAlignment */);
+                mFrameRateRange = Range.create(1, maxRate);
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ||
+                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+                maxBlocks = maxBlocksPerSecond = Integer.MAX_VALUE;
+
+                // TODO: set to 100Mbps for now, need a number for VPX
+                maxBps = 100000000;
+
+                // profile levels are not indicative for VPx, but verify
+                // them nonetheless
+                for (CodecProfileLevel profileLevel: profileLevels) {
+                    switch (profileLevel.level) {
+                        case CodecProfileLevel.VP8Level_Version0:
+                        case CodecProfileLevel.VP8Level_Version1:
+                        case CodecProfileLevel.VP8Level_Version2:
+                        case CodecProfileLevel.VP8Level_Version3:
+                            break;
+                        default:
+                            Log.w(TAG, "Unrecognized level "
+                                    + profileLevel.level + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    switch (profileLevel.profile) {
+                        case CodecProfileLevel.VP8ProfileMain:
+                            break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    errors &= ~ERROR_NONE_SUPPORTED;
+                }
+
+                final int blockSize =
+                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8;
+                applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
+                        maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
+                        1 /* widthAlignment */, 1 /* heightAlignment */);
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+                maxBlocks = 36864;
+                maxBlocksPerSecond = maxBlocks * 15;
+                maxBps = 128000;
+                for (CodecProfileLevel profileLevel: profileLevels) {
+                    double FR = 0;
+                    int FS = 0;
+                    int BR = 0;
+                    switch (profileLevel.level) {
+                        case CodecProfileLevel.HEVCMainTierLevel1:
+                        case CodecProfileLevel.HEVCHighTierLevel1:
+                            FR =    15; FS =    36864; BR =    128; break;
+                        case CodecProfileLevel.HEVCMainTierLevel2:
+                        case CodecProfileLevel.HEVCHighTierLevel2:
+                            FR =    30; FS =   122880; BR =   1500; break;
+                        case CodecProfileLevel.HEVCMainTierLevel21:
+                        case CodecProfileLevel.HEVCHighTierLevel21:
+                            FR =    30; FS =   245760; BR =   3000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel3:
+                        case CodecProfileLevel.HEVCHighTierLevel3:
+                            FR =    30; FS =   552960; BR =   6000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel31:
+                        case CodecProfileLevel.HEVCHighTierLevel31:
+                            FR = 33.75; FS =   983040; BR =  10000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel4:
+                            FR =    30; FS =  2228224; BR =  12000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel4:
+                            FR =    30; FS =  2228224; BR =  30000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel41:
+                            FR =    60; FS =  2228224; BR =  20000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel41:
+                            FR =    60; FS =  2228224; BR =  50000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel5:
+                            FR =    30; FS =  8912896; BR =  25000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel5:
+                            FR =    30; FS =  8912896; BR = 100000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel51:
+                            FR =    60; FS =  8912896; BR =  40000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel51:
+                            FR =    60; FS =  8912896; BR = 160000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel52:
+                            FR =   120; FS =  8912896; BR =  60000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel52:
+                            FR =   120; FS =  8912896; BR = 240000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel6:
+                            FR =    30; FS = 35651584; BR =  60000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel6:
+                            FR =    30; FS = 35651584; BR = 240000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel61:
+                            FR =    60; FS = 35651584; BR = 120000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel61:
+                            FR =    60; FS = 35651584; BR = 480000; break;
+                        case CodecProfileLevel.HEVCMainTierLevel62:
+                            FR =   120; FS = 35651584; BR = 240000; break;
+                        case CodecProfileLevel.HEVCHighTierLevel62:
+                            FR =   120; FS = 35651584; BR = 800000; break;
+                        default:
+                            Log.w(TAG, "Unrecognized level "
+                                    + profileLevel.level + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    switch (profileLevel.profile) {
+                        case CodecProfileLevel.HEVCProfileMain:
+                        case CodecProfileLevel.HEVCProfileMain10:
+                            break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+
+                    /* DPB logic:
+                    if      (width * height <= FS / 4)    DPB = 16;
+                    else if (width * height <= FS / 2)    DPB = 12;
+                    else if (width * height <= FS * 0.75) DPB = 8;
+                    else                                  DPB = 6;
+                    */
+
+                    errors &= ~ERROR_NONE_SUPPORTED;
+                    maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond);
+                    maxBlocks = Math.max(FS, maxBlocks);
+                    maxBps = Math.max(BR * 1000, maxBps);
+                }
+
+                int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
+                // CTBs are at least 8x8
+                maxBlocks = Utils.divUp(maxBlocks, 8 * 8);
+                maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, 8 * 8);
+                maxLengthInBlocks = Utils.divUp(maxLengthInBlocks, 8);
+
+                applyMacroBlockLimits(
+                        maxLengthInBlocks, maxLengthInBlocks,
+                        maxBlocks, maxBlocksPerSecond,
+                        8 /* blockWidth */, 8 /* blockHeight */,
+                        1 /* widthAlignment */, 1 /* heightAlignment */);
+            } else {
+                Log.w(TAG, "Unsupported mime " + mime);
+                // using minimal bitrate here.  should be overriden by
+                // info from media_codecs.xml
+                maxBps = 64000;
+                errors |= ERROR_UNSUPPORTED;
+            }
+            mBitrateRange = Range.create(1, maxBps);
+            mParent.mError |= errors;
+        }
+    }
+
+    /**
+     * A class that supports querying the encoding capabilities of a codec.
+     */
+    public static final class EncoderCapabilities {
+        /**
+         * Returns the supported range of quality values.
+         *
+         * @hide
+         */
+        public Range<Integer> getQualityRange() {
+            return mQualityRange;
+        }
+
+        /**
+         * Returns the supported range of encoder complexity values.
+         * <p>
+         * Some codecs may support multiple complexity levels, where higher
+         * complexity values use more encoder tools (e.g. perform more
+         * intensive calculations) to improve the quality or the compression
+         * ratio.  Use a lower value to save power and/or time.
+         */
+        public Range<Integer> getComplexityRange() {
+            return mComplexityRange;
+        }
+
+        /** Constant quality mode */
+        public static final int BITRATE_MODE_CQ = 0;
+        /** Variable bitrate mode */
+        public static final int BITRATE_MODE_VBR = 1;
+        /** Constant bitrate mode */
+        public static final int BITRATE_MODE_CBR = 2;
+
+        private static final Feature[] bitrates = new Feature[] {
+            new Feature("VBR", BITRATE_MODE_VBR, true),
+            new Feature("CBR", BITRATE_MODE_CBR, false),
+            new Feature("CQ",  BITRATE_MODE_CQ,  false)
+        };
+
+        private static int parseBitrateMode(String mode) {
+            for (Feature feat: bitrates) {
+                if (feat.mName.equalsIgnoreCase(mode)) {
+                    return feat.mValue;
+                }
+            }
+            return 0;
+        }
+
+        /**
+         * Query whether a bitrate mode is supported.
+         */
+        public boolean isBitrateModeSupported(int mode) {
+            for (Feature feat: bitrates) {
+                if (mode == feat.mValue) {
+                    return (mBitControl & (1 << mode)) != 0;
+                }
+            }
+            return false;
+        }
+
+        private Range<Integer> mQualityRange;
+        private Range<Integer> mComplexityRange;
+        private CodecCapabilities mParent;
+
+        /* no public constructor */
+        private EncoderCapabilities() { }
+
+        /** @hide */
+        public static EncoderCapabilities create(
+                MediaFormat info, CodecCapabilities parent) {
+            EncoderCapabilities caps = new EncoderCapabilities();
+            caps.init(info, parent);
+            return caps;
+        }
+
+        /** @hide */
+        public void init(MediaFormat info, CodecCapabilities parent) {
+            // no support for complexity or quality yet
+            mParent = parent;
+            mComplexityRange = Range.create(0, 0);
+            mQualityRange = Range.create(0, 0);
+            mBitControl = (1 << BITRATE_MODE_VBR);
+
+            applyLevelLimits();
+            parseFromInfo(info);
+        }
+
+        private void applyLevelLimits() {
+            String mime = mParent.getMimeType();
+            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+                mComplexityRange = Range.create(0, 8);
+                mBitControl = (1 << BITRATE_MODE_CQ);
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
+                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
+                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
+                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
+                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
+                mBitControl = (1 << BITRATE_MODE_CBR);
+            }
+        }
+
+        private int mBitControl;
+        private Integer mDefaultComplexity;
+        private Integer mDefaultQuality;
+        private String mQualityScale;
+
+        private void parseFromInfo(MediaFormat info) {
+            Map<String, Object> map = info.getMap();
+
+            if (info.containsKey("complexity-range")) {
+                mComplexityRange = Utils
+                        .parseIntRange(info.getString("complexity-range"), mComplexityRange);
+                // TODO should we limit this to level limits?
+            }
+            if (info.containsKey("quality-range")) {
+                mQualityRange = Utils
+                        .parseIntRange(info.getString("quality-range"), mQualityRange);
+            }
+            if (info.containsKey("feature-bitrate-control")) {
+                for (String mode: info.getString("feature-bitrate-control").split(",")) {
+                    mBitControl |= parseBitrateMode(mode);
+                }
+            }
+
+            try {
+                mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default"));
+            } catch (NumberFormatException e) { }
+
+            try {
+                mDefaultQuality = Integer.parseInt((String)map.get("quality-default"));
+            } catch (NumberFormatException e) { }
+
+            mQualityScale = (String)map.get("quality-scale");
+        }
+
+        private boolean supports(
+                Integer complexity, Integer quality, Integer profile) {
+            boolean ok = true;
+            if (ok && complexity != null) {
+                ok = mComplexityRange.contains(complexity);
+            }
+            if (ok && quality != null) {
+                ok = mQualityRange.contains(quality);
+            }
+            if (ok && profile != null) {
+                for (CodecProfileLevel pl: mParent.profileLevels) {
+                    if (pl.profile == profile) {
+                        profile = null;
+                        break;
+                    }
+                }
+                ok = profile == null;
+            }
+            return ok;
+        }
+
+        /** @hide */
+        public void setDefaultFormat(MediaFormat format) {
+            // don't list trivial quality/complexity as default for now
+            if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
+                    && mDefaultQuality != null) {
+                format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality);
+            }
+            if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower())
+                    && mDefaultComplexity != null) {
+                format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity);
+            }
+            // bitrates are listed in order of preference
+            for (Feature feat: bitrates) {
+                if ((mBitControl & (1 << feat.mValue)) != 0) {
+                    format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue);
+                    break;
+                }
+            }
+        }
+
+        /** @hide */
+        public boolean supportsFormat(MediaFormat format) {
+            final Map<String, Object> map = format.getMap();
+            final String mime = mParent.getMimeType();
+
+            Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE);
+            if (mode != null && !isBitrateModeSupported(mode)) {
+                return false;
+            }
+
+            Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY);
+            if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) {
+                Integer flacComplexity =
+                    (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL);
+                if (complexity == null) {
+                    complexity = flacComplexity;
+                } else if (flacComplexity != null && complexity != flacComplexity) {
+                    throw new IllegalArgumentException(
+                            "conflicting values for complexity and " +
+                            "flac-compression-level");
+                }
+            }
+
+            // other audio parameters
+            Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
+            if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) {
+                Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE);
+                if (profile == null) {
+                    profile = aacProfile;
+                } else if (aacProfile != null && aacProfile != profile) {
+                    throw new IllegalArgumentException(
+                            "conflicting values for profile and aac-profile");
+                }
+            }
+
+            Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY);
+
+            return supports(complexity, quality, profile);
         }
     };
 
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index d74f22d..5084c5c 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -36,6 +36,8 @@
     /**
      * Count the number of available (regular) codecs.
      *
+     * @deprecated Use {@link #getCodecInfos} instead.
+     *
      * @see #REGULAR_CODECS
      */
     public static final int getCodecCount() {
@@ -49,6 +51,8 @@
      * Return the {@link MediaCodecInfo} object for the codec at
      * the given {@code index} in the regular list.
      *
+     * @deprecated Use {@link #getCodecInfos} instead.
+     *
      * @see #REGULAR_CODECS
      */
     public static final MediaCodecInfo getCodecInfoAt(int index) {
@@ -116,13 +120,22 @@
 
     /**
      * Use in {@link #MediaCodecList} to enumerate only codecs that are suitable
-     * for normal playback and recording.
+     * for regular (buffer-to-buffer) decoding or encoding.
+     *
+     * <em>NOTE:</em> These are the codecs that are returned prior to API 21,
+     * using the now deprecated static methods.
      */
     public static final int REGULAR_CODECS = 0;
 
     /**
      * Use in {@link #MediaCodecList} to enumerate all codecs, even ones that are
-     * not suitable for normal playback or recording.
+     * not suitable for regular (buffer-to-buffer) decoding or encoding.  These
+     * include codecs, for example, that only work with special input or output
+     * surfaces, such as secure-only or tunneled-only codecs.
+     *
+     * @see MediaCodecInfo.CodecCapabilities#isFormatSupported
+     * @see MediaCodecInfo.CodecCapabilities#FEATURE_SecurePlayback
+     * @see MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback
      */
     public static final int ALL_CODECS = 1;
 
diff --git a/media/java/android/media/MediaDescription.aidl b/media/java/android/media/MediaDescription.aidl
new file mode 100644
index 0000000..6f934f7
--- /dev/null
+++ b/media/java/android/media/MediaDescription.aidl
@@ -0,0 +1,18 @@
+/* Copyright 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.media;
+
+parcelable MediaDescription;
diff --git a/media/java/android/media/MediaDescription.java b/media/java/android/media/MediaDescription.java
new file mode 100644
index 0000000..4399c0d
--- /dev/null
+++ b/media/java/android/media/MediaDescription.java
@@ -0,0 +1,276 @@
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Size;
+
+/**
+ * A simple set of metadata for a media item suitable for display. This can be
+ * created using the Builder or retrieved from existing metadata using
+ * {@link MediaMetadata#getDescription()}.
+ */
+public class MediaDescription implements Parcelable {
+    /**
+     * A unique persistent id for the content or null.
+     */
+    private final String mMediaId;
+    /**
+     * A primary title suitable for display or null.
+     */
+    private final CharSequence mTitle;
+    /**
+     * A subtitle suitable for display or null.
+     */
+    private final CharSequence mSubtitle;
+    /**
+     * A description suitable for display or null.
+     */
+    private final CharSequence mDescription;
+    /**
+     * A bitmap icon suitable for display or null.
+     */
+    private final Bitmap mIcon;
+    /**
+     * A Uri for an icon suitable for display or null.
+     */
+    private final Uri mIconUri;
+    /**
+     * Extras for opaque use by apps/system.
+     */
+    private final Bundle mExtras;
+
+    private MediaDescription(String mediaId, CharSequence title, CharSequence subtitle,
+            CharSequence description, Bitmap icon, Uri iconUri, Bundle extras) {
+        mMediaId = mediaId;
+        mTitle = title;
+        mSubtitle = subtitle;
+        mDescription = description;
+        mIcon = icon;
+        mIconUri = iconUri;
+        mExtras = extras;
+    }
+
+    private MediaDescription(Parcel in) {
+        mMediaId = in.readString();
+        mTitle = in.readCharSequence();
+        mSubtitle = in.readCharSequence();
+        mDescription = in.readCharSequence();
+        mIcon = in.readParcelable(null);
+        mIconUri = in.readParcelable(null);
+        mExtras = in.readBundle();
+    }
+
+    /**
+     * Returns the media id or null. See
+     * {@link MediaMetadata#METADATA_KEY_MEDIA_ID}.
+     */
+    public @Nullable String getMediaId() {
+        return mMediaId;
+    }
+
+    /**
+     * Returns a title suitable for display or null.
+     *
+     * @return A title or null.
+     */
+    public @Nullable CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns a subtitle suitable for display or null.
+     *
+     * @return A subtitle or null.
+     */
+    public @Nullable CharSequence getSubtitle() {
+        return mSubtitle;
+    }
+
+    /**
+     * Returns a description suitable for display or null.
+     *
+     * @return A description or null.
+     */
+    public @Nullable CharSequence getDescription() {
+        return mDescription;
+    }
+
+    /**
+     * Returns a bitmap icon suitable for display or null.
+     *
+     * @return An icon or null.
+     */
+    public @Nullable Bitmap getIconBitmap() {
+        return mIcon;
+    }
+
+    /**
+     * Returns a Uri for an icon suitable for display or null.
+     *
+     * @return An icon uri or null.
+     */
+    public @Nullable Uri getIconUri() {
+        return mIconUri;
+    }
+
+    /**
+     * Returns any extras that were added to the description.
+     *
+     * @return A bundle of extras or null.
+     */
+    public @Nullable Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mMediaId);
+        dest.writeCharSequence(mTitle);
+        dest.writeCharSequence(mSubtitle);
+        dest.writeCharSequence(mDescription);
+        dest.writeParcelable(mIcon, flags);
+        dest.writeParcelable(mIconUri, flags);
+        dest.writeBundle(mExtras);
+    }
+
+    @Override
+    public String toString() {
+        return mTitle + ", " + mSubtitle + ", " + mDescription;
+    }
+
+    public static final Parcelable.Creator<MediaDescription> CREATOR =
+            new Parcelable.Creator<MediaDescription>() {
+                @Override
+                public MediaDescription createFromParcel(Parcel in) {
+                    return new MediaDescription(in);
+                }
+
+                @Override
+                public MediaDescription[] newArray(int size) {
+                    return new MediaDescription[size];
+                }
+            };
+
+    /**
+     * Builder for {@link MediaDescription} objects.
+     */
+    public static class Builder {
+        private String mMediaId;
+        private CharSequence mTitle;
+        private CharSequence mSubtitle;
+        private CharSequence mDescription;
+        private Bitmap mIcon;
+        private Uri mIconUri;
+        private Bundle mExtras;
+
+        /**
+         * Creates an initially empty builder.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Sets the media id.
+         *
+         * @param mediaId The unique id for the item or null.
+         * @return this
+         */
+        public Builder setMediaId(@Nullable String mediaId) {
+            mMediaId = mediaId;
+            return this;
+        }
+
+        /**
+         * Sets the title.
+         *
+         * @param title A title suitable for display to the user or null.
+         * @return this
+         */
+        public Builder setTitle(@Nullable CharSequence title) {
+            mTitle = title;
+            return this;
+        }
+
+        /**
+         * Sets the subtitle.
+         *
+         * @param subtitle A subtitle suitable for display to the user or null.
+         * @return this
+         */
+        public Builder setSubtitle(@Nullable CharSequence subtitle) {
+            mSubtitle = subtitle;
+            return this;
+        }
+
+        /**
+         * Sets the description.
+         *
+         * @param description A description suitable for display to the user or
+         *            null.
+         * @return this
+         */
+        public Builder setDescription(@Nullable CharSequence description) {
+            mDescription = description;
+            return this;
+        }
+
+        /**
+         * Sets the icon.
+         *
+         * @param icon A {@link Bitmap} icon suitable for display to the user or
+         *            null.
+         * @return this
+         */
+        public Builder setIconBitmap(@Nullable Bitmap icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        /**
+         * Sets the icon uri.
+         *
+         * @param iconUri A {@link Uri} for an icon suitable for display to the
+         *            user or null.
+         * @return this
+         */
+        public Builder setIconUri(@Nullable Uri iconUri) {
+            mIconUri = iconUri;
+            return this;
+        }
+
+        /**
+         * Sets a bundle of extras.
+         *
+         * @param extras The extras to include with this description or null.
+         * @return this
+         */
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        public MediaDescription build() {
+            return new MediaDescription(mMediaId, mTitle, mSubtitle, mDescription, mIcon, mIconUri,
+                    mExtras);
+        }
+    }
+}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index fd79495..2036533 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -120,19 +120,6 @@
     private Map<String, Object> mMap;
 
     /**
-     * A key prefix used together with a {@link MediaCodecInfo.CodecCapabilities}
-     * feature name describing a required or optional feature for a codec capabilities
-     * query.
-     * The associated value is an integer, where non-0 value means the feature is
-     * requested to be present, while 0 value means the feature is requested to be not
-     * present.
-     * @see MediaCodecList#findDecoderForFormat
-     * @see MediaCodecList#findEncoderForFormat
-     * @see MediaCodecInfo.CodecCapabilities#isFormatSupported
-     */
-    public static final String KEY_FEATURE_ = "feature-";
-
-    /**
      * A key describing the mime type of the MediaFormat.
      * The associated value is a string.
      */
@@ -422,6 +409,8 @@
      * codec specific, but lower values generally result in more efficient
      * (smaller-sized) encoding.
      *
+     * @hide
+     *
      * @see MediaCodecInfo.CodecCapabilities.EncoderCapabilities#getQualityRange
      */
     public static final String KEY_QUALITY = "quality";
@@ -510,6 +499,21 @@
     }
 
     /**
+     * A key prefix used together with a {@link MediaCodecInfo.CodecCapabilities}
+     * feature name describing a required or optional feature for a codec capabilities
+     * query.
+     * The associated value is an integer, where non-0 value means the feature is
+     * requested to be present, while 0 value means the feature is requested to be not
+     * present.
+     * @see MediaCodecList#findDecoderForFormat
+     * @see MediaCodecList#findEncoderForFormat
+     * @see MediaCodecInfo.CodecCapabilities#isFormatSupported
+     *
+     * @hide
+     */
+    public static final String KEY_FEATURE_ = "feature-";
+
+    /**
      * Returns the value of an integer key.
      */
     public final int getInteger(String name) {
@@ -559,6 +563,23 @@
     }
 
     /**
+     * Returns whether a feature is to be enabled ({@code true}) or disabled
+     * ({@code false}).
+     *
+     * @param feature the name of a {@link MediaCodecInfo.CodecCapabilities} feature.
+     *
+     * @throws IllegalArgumentException if the feature was neither set to be enabled
+     *        nor to be disabled.
+     */
+    public boolean getFeatureEnabled(String feature) {
+        Integer enabled = (Integer)mMap.get(KEY_FEATURE_ + feature);
+        if (enabled == null) {
+            throw new IllegalArgumentException("feature is not specified");
+        }
+        return enabled != 0;
+    }
+
+    /**
      * Sets the value of an integer key.
      */
     public final void setInteger(String name, int value) {
@@ -594,6 +615,23 @@
     }
 
     /**
+     * Sets whether a feature is to be enabled ({@code true}) or disabled
+     * ({@code false}).
+     *
+     * If {@code enabled} is {@code true}, the feature is requested to be present.
+     * Otherwise, the feature is requested to be not present.
+     *
+     * @param feature the name of a {@link MediaCodecInfo.CodecCapabilities} feature.
+     *
+     * @see MediaCodecList#findDecoderForFormat
+     * @see MediaCodecList#findEncoderForFormat
+     * @see MediaCodecInfo.CodecCapabilities#isFormatSupported
+     */
+    public void setFeatureEnabled(String feature, boolean enabled) {
+        setInteger(KEY_FEATURE_ + feature, enabled ? 1 : 0);
+    }
+
+    /**
      * Creates a minimal audio format.
      * @param mime The mime type of the content.
      * @param sampleRate The sampling rate of the content.
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 74f7a96..b4e6033 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -17,15 +17,22 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.browse.MediaBrowser;
+import android.media.session.MediaController;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
-import android.text.format.Time;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Size;
 import android.util.SparseArray;
 
 import java.util.Set;
@@ -119,7 +126,9 @@
     public static final String METADATA_KEY_ART = "android.media.metadata.ART";
 
     /**
-     * The artwork for the media as a Uri.
+     * The artwork for the media as a Uri formatted String. The artwork can be
+     * loaded using a combination of {@link ContentResolver#openInputStream} and
+     * {@link BitmapFactory#decodeStream}.
      */
     public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
 
@@ -130,7 +139,10 @@
     public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
 
     /**
-     * The artwork for the album of the media's original source as a Uri.
+     * The artwork for the album of the media's original source as a Uri
+     * formatted String. The artwork can be loaded using a combination of
+     * {@link ContentResolver#openInputStream} and
+     * {@link BitmapFactory#decodeStream}.
      */
     public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
 
@@ -181,13 +193,26 @@
             = "android.media.metadata.DISPLAY_ICON";
 
     /**
-     * An icon or thumbnail that is suitable for display to the user. When
-     * displaying more information for media described by this metadata the
-     * display description should be preferred to other fields when present.
+     * A Uri formatted String for an icon or thumbnail that is suitable for
+     * display to the user. When displaying more information for media described
+     * by this metadata the display description should be preferred to other
+     * fields when present. The icon can be loaded using a combination of
+     * {@link ContentResolver#openInputStream} and
+     * {@link BitmapFactory#decodeStream}.
      */
     public static final String METADATA_KEY_DISPLAY_ICON_URI
             = "android.media.metadata.DISPLAY_ICON_URI";
 
+    /**
+     * A String key for identifying the content. This value is specific to the
+     * service providing the content. If used, this should be a persistent
+     * unique key for the underlying content. It may be used with
+     * {@link MediaController.TransportControls#playFromMediaId(String, Bundle)}
+     * to initiate playback when provided by a {@link MediaBrowser} connected to
+     * the same app.
+     */
+    public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+
     private static final String[] PREFERRED_DESCRIPTION_ORDER = {
             METADATA_KEY_TITLE,
             METADATA_KEY_ARTIST,
@@ -277,7 +302,7 @@
     }
 
     private final Bundle mBundle;
-    private Description mDescription;
+    private MediaDescription mDescription;
 
     private MediaMetadata(Bundle bundle) {
         mBundle = new Bundle(bundle);
@@ -406,11 +431,13 @@
      *
      * @return A simple description of this metadata.
      */
-    public @NonNull Description getDescription() {
+    public @NonNull MediaDescription getDescription() {
         if (mDescription != null) {
             return mDescription;
         }
 
+        String mediaId = getString(METADATA_KEY_MEDIA_ID);
+
         CharSequence[] text = new CharSequence[3];
         Bitmap icon = null;
         Uri iconUri = null;
@@ -454,7 +481,15 @@
             }
         }
 
-        mDescription = new Description(text[0], text[1], text[2], icon, iconUri);
+        MediaDescription.Builder bob = new MediaDescription.Builder();
+        bob.setMediaId(mediaId);
+        bob.setTitle(text[0]);
+        bob.setSubtitle(text[1]);
+        bob.setDescription(text[2]);
+        bob.setIconBitmap(icon);
+        bob.setIconUri(iconUri);
+        mDescription = bob.build();
+
         return mDescription;
     }
 
@@ -668,90 +703,4 @@
             return new MediaMetadata(mBundle);
         }
     }
-
-    /**
-     * A simple form of the metadata that can be used for display.
-     */
-    public final class Description {
-        /**
-         * A primary title suitable for display or null.
-         */
-        private final CharSequence mTitle;
-        /**
-         * A subtitle suitable for display or null.
-         */
-        private final CharSequence mSubtitle;
-        /**
-         * A description suitable for display or null.
-         */
-        private final CharSequence mDescription;
-        /**
-         * A bitmap icon suitable for display or null.
-         */
-        private final Bitmap mIcon;
-        /**
-         * A Uri for an icon suitable for display or null.
-         */
-        private final Uri mIconUri;
-
-        /**
-         * Returns the best available title or null.
-         *
-         * @return A title or null.
-         */
-        public @Nullable CharSequence getTitle() {
-            return mTitle;
-        }
-
-        /**
-         * Returns the best available subtitle or null.
-         *
-         * @return A subtitle or null.
-         */
-        public @Nullable CharSequence getSubtitle() {
-            return mSubtitle;
-        }
-
-        /**
-         * Returns the best available description or null.
-         *
-         * @return A description or null.
-         */
-        public @Nullable CharSequence getDescription() {
-            return mDescription;
-        }
-
-        /**
-         * Returns the best available icon or null.
-         *
-         * @return An icon or null.
-         */
-        public @Nullable Bitmap getIcon() {
-            return mIcon;
-        }
-
-        /**
-         * Returns the best available icon Uri or null.
-         *
-         * @return An icon uri or null.
-         */
-        public @Nullable Uri getIconUri() {
-            return mIconUri;
-        }
-
-        private Description(CharSequence title, CharSequence subtitle, CharSequence description,
-                Bitmap icon, Uri iconUri) {
-            mTitle = title;
-            mSubtitle = subtitle;
-            mDescription = description;
-            mIcon = icon;
-            mIconUri = iconUri;
-        }
-
-        @Override
-        public String toString() {
-            return mTitle + ", " + mSubtitle + ", " + mDescription;
-        }
-    }
-
 }
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index a221104..7d075ba 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -115,6 +115,15 @@
     }
 
     /**
+     * Returns the {@link AudioAttributes} used by this object.
+     * @return the {@link AudioAttributes} that were set with
+     *     {@link #setAudioAttributes(AudioAttributes)} or the default attributes if none were set.
+     */
+    public AudioAttributes getAudioAttributes() {
+        return mAudioAttributes;
+    }
+
+    /**
      * Returns a human-presentable title for ringtone. Looks in media
      * content provider. If not in either, uses the filename
      * 
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 9b9c767..4f74bdd 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -151,6 +151,10 @@
 
         /**
          * Constructs a new Builder with the defaults format values.
+         * If not provided, the maximum number of streams is 1 (see {@link #setMaxStreams(int)} to
+         * change it), and the audio attributes have a usage value of
+         * {@link AudioAttributes#USAGE_MEDIA} (see {@link #setAudioAttributes(AudioAttributes)} to
+         * change them).
          */
         public Builder() {
         }
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 1c6d81f..debaf45 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -16,6 +16,7 @@
 
 package android.media.browse;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
@@ -23,26 +24,27 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.pm.ParceledListSlice;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
+import android.media.MediaDescription;
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.RemoteException;
+import android.service.media.MediaBrowserService;
+import android.service.media.IMediaBrowserService;
+import android.service.media.IMediaBrowserServiceCallbacks;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.SparseArray;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Objects;
-import java.util.Set;
 
 /**
  * Browses media content offered by a link MediaBrowserService.
@@ -67,8 +69,6 @@
     private final Handler mHandler = new Handler();
     private final ArrayMap<Uri,Subscription> mSubscriptions =
             new ArrayMap<Uri, MediaBrowser.Subscription>();
-    private final SparseArray<IconRequest> mIconRequests =
-            new SparseArray<IconRequest>();
 
     private int mState = CONNECT_STATE_DISCONNECTED;
     private MediaServiceConnection mServiceConnection;
@@ -77,7 +77,6 @@
     private Uri mRootUri;
     private MediaSession.Token mMediaSessionToken;
     private Bundle mExtras;
-    private int mNextSeq;
 
     /**
      * Creates a media browser for the specified media browse service.
@@ -363,49 +362,6 @@
     }
 
     /**
-     * Loads the icon of a media item.
-     *
-     * @param uri The uri of the Icon.
-     * @param width The preferred width of the icon in dp.
-     * @param height The preferred width of the icon in dp.
-     * @param callback The callback to receive the icon.
-     */
-    public void loadIcon(final @NonNull Uri uri, final int width, final int height,
-            final @NonNull IconCallback callback) {
-        if (uri == null) {
-            throw new IllegalArgumentException("Icon uri cannot be null");
-        }
-        if (callback == null) {
-            throw new IllegalArgumentException("Icon callback cannot be null");
-        }
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                for (int i = 0; i < mIconRequests.size(); i++) {
-                    IconRequest existingRequest = mIconRequests.valueAt(i);
-                    if (existingRequest.isSameRequest(uri, width, height)) {
-                        existingRequest.addCallback(callback);
-                        return;
-                    }
-                }
-                final int seq = mNextSeq++;
-                IconRequest request = new IconRequest(seq, uri, width, height);
-                request.addCallback(callback);
-                mIconRequests.put(seq, request);
-                if (mState == CONNECT_STATE_CONNECTED) {
-                    try {
-                        mServiceBinder.loadIcon(seq, uri, width, height, mServiceCallbacks);
-                    } catch (RemoteException e) {
-                        // Process is crashing.  We will disconnect, and upon reconnect we will
-                        // automatically reload the icons. So nothing to do here.
-                        Log.d(TAG, "loadIcon failed with RemoteException uri=" + uri);
-                    }
-                }
-            }
-        });
-    }
-
-    /**
      * For debugging.
      */
     private static String getStateLabel(int state) {
@@ -461,18 +417,6 @@
                         Log.d(TAG, "addSubscription failed with RemoteException parentUri=" + uri);
                     }
                 }
-
-                for (int i = 0; i < mIconRequests.size(); i++) {
-                    IconRequest request = mIconRequests.valueAt(i);
-                    try {
-                        mServiceBinder.loadIcon(request.mSeq, request.mUri,
-                                request.mWidth, request.mHeight, mServiceCallbacks);
-                    } catch (RemoteException e) {
-                        // Process is crashing.  We will disconnect, and upon reconnect we will
-                        // automatically reload. So nothing to do here.
-                        Log.d(TAG, "loadIcon failed with RemoteException request=" + request);
-                    }
-                }
             }
         });
     }
@@ -515,7 +459,7 @@
                     return;
                 }
 
-                List<MediaBrowserItem> data = list.getList();
+                List<MediaItem> data = list.getList();
                 if (DBG) {
                     Log.d(TAG, "onLoadChildren for " + mServiceComponent + " uri=" + uri);
                 }
@@ -539,32 +483,6 @@
         });
     }
 
-    private final void onLoadIcon(final IMediaBrowserServiceCallbacks callback,
-            final int seqNum, final Bitmap bitmap) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                // Check that there hasn't been a disconnect or a different
-                // ServiceConnection.
-                if (!isCurrent(callback, "onLoadIcon")) {
-                    return;
-                }
-
-                IconRequest request = mIconRequests.get(seqNum);
-                if (request == null) {
-                    Log.d(TAG, "onLoadIcon called for seqNum=" + seqNum + " request="
-                            + request + " but the request is not registered");
-                    return;
-                }
-                mIconRequests.delete(seqNum);
-                for (IconCallback IconCallback : request.getCallbacks()) {
-                    IconCallback.onIconLoaded(request.mUri, bitmap);
-                }
-            }
-        });
-    }
-
-
     /**
      * Return true if {@code callback} is the current ServiceCallbacks.  Also logs if it's not.
      */
@@ -600,6 +518,126 @@
         Log.d(TAG, "  mMediaSessionToken=" + mMediaSessionToken);
     }
 
+    public static class MediaItem implements Parcelable {
+        private final int mFlags;
+        private final MediaDescription mDescription;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE })
+        public @interface Flags { }
+
+        /**
+         * Flag: Indicates that the item has children of its own.
+         */
+        public static final int FLAG_BROWSABLE = 1 << 0;
+
+        /**
+         * Flag: Indicates that the item is playable.
+         * <p>
+         * The Uri of this item may be passed to link android.media.session.MediaController#play(Uri)
+         * to start playing it.
+         * </p>
+         */
+        public static final int FLAG_PLAYABLE = 1 << 1;
+
+        /**
+         * Create a new MediaItem for use in browsing media.
+         *
+         * @param flags The flags for this item.
+         * @param description The description of the media, which must include a
+         *            media id.
+         */
+        public MediaItem(@Flags int flags, @NonNull MediaDescription description) {
+            if (description == null) {
+                throw new IllegalArgumentException("description cannot be null");
+            }
+            if (TextUtils.isEmpty(description.getMediaId())) {
+                throw new IllegalArgumentException("description must have a non-empty media id");
+            }
+            mFlags = flags;
+            mDescription = description;
+        }
+
+        /**
+         * Private constructor.
+         */
+        private MediaItem(Parcel in) {
+            mFlags = in.readInt();
+            mDescription = MediaDescription.CREATOR.createFromParcel(in);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(mFlags);
+            mDescription.writeToParcel(out, flags);
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("MediaItem{");
+            sb.append("mFlags=").append(mFlags);
+            sb.append(", mDescription=").append(mDescription);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        public static final Parcelable.Creator<MediaItem> CREATOR =
+                new Parcelable.Creator<MediaItem>() {
+                    @Override
+                    public MediaItem createFromParcel(Parcel in) {
+                        return new MediaItem(in);
+                    }
+
+                    @Override
+                    public MediaItem[] newArray(int size) {
+                        return new MediaItem[size];
+                    }
+                };
+
+        /**
+         * Gets the flags of the item.
+         */
+        public @Flags int getFlags() {
+            return mFlags;
+        }
+
+        /**
+         * Returns whether this item is browsable.
+         * @see #FLAG_BROWSABLE
+         */
+        public boolean isBrowsable() {
+            return (mFlags & FLAG_BROWSABLE) != 0;
+        }
+
+        /**
+         * Returns whether this item is playable.
+         * @see #FLAG_PLAYABLE
+         */
+        public boolean isPlayable() {
+            return (mFlags & FLAG_PLAYABLE) != 0;
+        }
+
+        /**
+         * Returns the description of the media.
+         */
+        public @NonNull MediaDescription getDescription() {
+            return mDescription;
+        }
+
+        /**
+         * Returns the media id for this item.
+         */
+        public @NonNull String getMediaId() {
+            return mDescription.getMediaId();
+        }
+    }
+
 
     /**
      * Callbacks for connection related events.
@@ -632,7 +670,7 @@
          * Called when the list of children is loaded or updated.
          */
         public void onChildrenLoaded(@NonNull Uri parentUri,
-                                     @NonNull List<MediaBrowserItem> children) {
+                                     @NonNull List<MediaItem> children) {
         }
 
         /**
@@ -647,87 +685,6 @@
     }
 
     /**
-     * Callbacks for icon loading.
-     */
-    public static abstract class IconCallback {
-        /**
-         * Called when the icon is loaded.
-         */
-        public void onIconLoaded(@NonNull Uri uri, @NonNull Bitmap bitmap) {
-        }
-
-        /**
-         * Called when the Uri doesn’t exist or the bitmap cannot be loaded.
-         */
-        public void onError(@NonNull Uri uri) {
-        }
-    }
-
-    private static class IconRequest {
-        final int mSeq;
-        final Uri mUri;
-        final int mWidth;
-        final int mHeight;
-        final List<IconCallback> mCallbacks;
-
-        /**
-         * Constructs an icon request.
-         * @param seq The unique sequence number assigned to the request by the media browser.
-         * @param uri The Uri for the icon.
-         * @param width The width for the icon.
-         * @param height The height for the icon.
-         */
-        IconRequest(int seq, @NonNull Uri uri, int width, int height) {
-            if (uri == null) {
-                throw new IllegalArgumentException("Icon uri cannot be null");
-            }
-            this.mSeq = seq;
-            this.mUri = uri;
-            this.mWidth = width;
-            this.mHeight = height;
-            mCallbacks = new ArrayList<IconCallback>();
-        }
-
-        /**
-         * Adds a callback to the icon request.
-         * If the callback already exists, it will not be added again.
-         */
-        public void addCallback(@NonNull IconCallback callback) {
-            if (callback == null) {
-                throw new IllegalArgumentException("callback cannot be null in IconRequest");
-            }
-            if (!mCallbacks.contains(callback)) {
-                mCallbacks.add(callback);
-            }
-        }
-
-        /**
-         * Checks if the icon request has the same uri, width, and height as the given values.
-         */
-        public boolean isSameRequest(@Nullable Uri uri, int width, int height) {
-            return Objects.equals(mUri, uri) && mWidth == width && mHeight == height;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder sb = new StringBuilder("IconRequest{");
-            sb.append("uri=").append(mUri);
-            sb.append(", width=").append(mWidth);
-            sb.append(", height=").append(mHeight);
-            sb.append(", seq=").append(mSeq);
-            sb.append('}');
-            return sb.toString();
-        }
-
-        /**
-         * Gets an unmodifiable view of the list of callbacks associated with the request.
-         */
-        public List<IconCallback> getCallbacks() {
-            return Collections.unmodifiableList(mCallbacks);
-        }
-    }
-
-    /**
      * ServiceConnection to the other app.
      */
     private class MediaServiceConnection implements ServiceConnection {
@@ -809,7 +766,7 @@
             }
             return true;
         }
-    };
+    }
 
     /**
      * Callbacks from the service.
@@ -852,14 +809,6 @@
                 mediaBrowser.onLoadChildren(this, uri, list);
             }
         }
-
-        @Override
-        public void onLoadIcon(final int seqNum, final Bitmap bitmap) {
-            MediaBrowser mediaBrowser = mMediaBrowser.get();
-            if (mediaBrowser != null) {
-                mediaBrowser.onLoadIcon(this, seqNum, bitmap);
-            }
-        }
     }
 
     private static class Subscription {
diff --git a/media/java/android/media/browse/MediaBrowserItem.java b/media/java/android/media/browse/MediaBrowserItem.java
deleted file mode 100644
index 47ec46b..0000000
--- a/media/java/android/media/browse/MediaBrowserItem.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.browse;
-
-import android.annotation.DrawableRes;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.net.Uri;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Describes a media item in the list of items offered by a {@link MediaBrowserService}.
- */
-public final class MediaBrowserItem implements Parcelable {
-    private final Uri mUri;
-    private final int mFlags;
-    private final CharSequence mTitle;
-    private final CharSequence mSummary;
-    private final Uri mIconUri;
-    private final int mIconResourceId;
-    private final Bundle mExtras;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE })
-    public @interface Flags { }
-
-    /**
-     * Flag: Indicates that the item has children of its own.
-     */
-    public static final int FLAG_BROWSABLE = 1 << 0;
-
-    /**
-     * Flag: Indicates that the item is playable.
-     * <p>
-     * The Uri of this item may be passed to link android.media.session.MediaController#play(Uri)
-     * to start playing it.
-     * </p>
-     */
-    public static final int FLAG_PLAYABLE = 1 << 1;
-
-    /**
-     * Initialize a MediaBrowserItem object.
-     */
-    private MediaBrowserItem(@NonNull Uri uri, int flags, @NonNull CharSequence title,
-            CharSequence summary, @Nullable Uri iconUri, int iconResourceId, Bundle extras) {
-        if (uri == null) {
-            throw new IllegalArgumentException("uri can not be null");
-        }
-        if (title == null) {
-            throw new IllegalArgumentException("title can not be null");
-        }
-        mUri = uri;
-        mFlags = flags;
-        mTitle = title;
-        mSummary = summary;
-        mIconUri = iconUri;
-        mIconResourceId = iconResourceId;
-        mExtras = extras;
-    }
-
-    /**
-     * Private constructor.
-     */
-    private MediaBrowserItem(Parcel in) {
-        mUri = Uri.CREATOR.createFromParcel(in);
-        mFlags = in.readInt();
-        mTitle = in.readCharSequence();
-        if (in.readInt() != 0) {
-            mSummary = in.readCharSequence();
-        } else {
-            mSummary = null;
-        }
-        if (in.readInt() != 0) {
-            mIconUri = Uri.CREATOR.createFromParcel(in);
-        } else {
-            mIconUri = null;
-        }
-        mIconResourceId = in.readInt();
-        if (in.readInt() != 0) {
-            mExtras = Bundle.CREATOR.createFromParcel(in);
-        } else {
-            mExtras = null;
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        mUri.writeToParcel(out, flags);
-        out.writeInt(mFlags);
-        out.writeCharSequence(mTitle);
-        if (mSummary != null) {
-            out.writeInt(1);
-            out.writeCharSequence(mSummary);
-        } else {
-            out.writeInt(0);
-        }
-        if (mIconUri != null) {
-            out.writeInt(1);
-            mIconUri.writeToParcel(out, flags);
-        } else {
-            out.writeInt(0);
-        }
-        out.writeInt(mIconResourceId);
-        if (mExtras != null) {
-            out.writeInt(1);
-            mExtras.writeToParcel(out, flags);
-        } else {
-            out.writeInt(0);
-        }
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder("MediaBrowserItem{");
-        sb.append("mUri=").append(mUri);
-        sb.append(", mFlags=").append(mFlags);
-        sb.append(", mTitle=").append(mTitle);
-        sb.append(", mSummary=").append(mSummary);
-        sb.append(", mIconUri=").append(mIconUri);
-        sb.append(", mIconResourceId=").append(mIconResourceId);
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public static final Parcelable.Creator<MediaBrowserItem> CREATOR =
-            new Parcelable.Creator<MediaBrowserItem>() {
-                @Override
-                public MediaBrowserItem createFromParcel(Parcel in) {
-                    return new MediaBrowserItem(in);
-                }
-
-                @Override
-                public MediaBrowserItem[] newArray(int size) {
-                    return new MediaBrowserItem[size];
-                }
-            };
-
-    /**
-     * Gets the Uri of the item.
-     */
-    public @NonNull Uri getUri() {
-        return mUri;
-    }
-
-    /**
-     * Gets the flags of the item.
-     */
-    public @Flags int getFlags() {
-        return mFlags;
-    }
-
-    /**
-     * Returns whether this item is browsable.
-     * @see #FLAG_BROWSABLE
-     */
-    public boolean isBrowsable() {
-        return (mFlags & FLAG_BROWSABLE) != 0;
-    }
-
-    /**
-     * Returns whether this item is playable.
-     * @see #FLAG_PLAYABLE
-     */
-    public boolean isPlayable() {
-        return (mFlags & FLAG_PLAYABLE) != 0;
-    }
-
-    /**
-     * Gets the title of the item.
-     * @more
-     * The title will be shown as the first line of text when
-     * describing each item to the user.
-     */
-    public @NonNull CharSequence getTitle() {
-        return mTitle;
-    }
-
-    /**
-     * Gets summary of the item, or null if none.
-     * @more
-     * The summary will be shown as the second line of text when
-     * describing each item to the user.
-     */
-    public @Nullable CharSequence getSummary() {
-        return mSummary;
-    }
-
-    /**
-     * Gets the Uri of the icon.
-     */
-    public @Nullable Uri getIconUri() {
-        return mIconUri;
-    }
-
-    /**
-     * Gets the resource id of the icon.
-     */
-    public @DrawableRes int getIconResourceId() {
-        return mIconResourceId;
-    }
-
-    /**
-     * Gets additional service-specified extras about the
-     * item or its content, or null if none.
-     */
-    public @Nullable Bundle getExtras() {
-        return mExtras;
-    }
-
-    /**
-     * Builder for {@link MediaBrowserItem} objects.
-     */
-    public static final class Builder {
-        private final Uri mUri;
-        private final int mFlags;
-        private final CharSequence mTitle;
-        private CharSequence mSummary;
-        private Uri mIconUri;
-        private int mIconResourceId;
-        private Bundle mExtras;
-
-        /**
-         * Creates an item builder.
-         */
-        public Builder(@NonNull Uri uri, @Flags int flags, @NonNull CharSequence title) {
-            if (uri == null) {
-                throw new IllegalArgumentException("uri can not be null");
-            }
-            if (title == null) {
-                throw new IllegalArgumentException("title can not be null");
-            }
-            mUri = uri;
-            mFlags = flags;
-            mTitle = title;
-        }
-
-        /**
-         * Sets summary of the item, or null if none.
-         */
-        public @NonNull Builder setSummary(@Nullable CharSequence summary) {
-            mSummary = summary;
-            return this;
-        }
-
-        /**
-         * Sets the uri of the icon.
-         * <p>
-         * Either {@link #setIconUri(Uri)} or {@link #setIconResourceId(int)} should be called.
-         * If both are specified, the resource id will be used to load the icon.
-         * </p>
-         */
-        public @NonNull Builder setIconUri(@Nullable Uri iconUri) {
-            mIconUri = iconUri;
-            return this;
-        }
-
-        /**
-         * Sets the resource id of the icon.
-         * <p>
-         * Either {@link #setIconUri(Uri)} or {@link #setIconResourceId(int)} should be specified.
-         * If both are specified, the resource id will be used to load the icon.
-         * </p>
-         */
-        public @NonNull Builder setIconResourceId(@DrawableRes int ResourceId) {
-            mIconResourceId = ResourceId;
-            return this;
-        }
-
-        /**
-         * Sets additional service-specified extras about the
-         * item or its content.
-         */
-        public @NonNull Builder setExtras(@Nullable Bundle extras) {
-            mExtras = extras;
-            return this;
-        }
-
-        /**
-         * Builds the item.
-         */
-        public @NonNull MediaBrowserItem build() {
-            return new MediaBrowserItem(mUri, mFlags, mTitle, mSummary, mIconUri,
-                    mIconResourceId, mExtras);
-        }
-    }
-}
-
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 9911129..49087b0 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -30,7 +30,7 @@
 
     // These callbacks are for the TransportPerformer
     void onPlay();
-    void onPlayUri(in Uri uri, in Bundle extras);
+    void onPlayFromMediaId(String uri, in Bundle extras);
     void onPlayFromSearch(String query, in Bundle extras);
     void onSkipToTrack(long id);
     void onPause();
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 6b80477..d684688 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -51,9 +51,9 @@
 
     // These commands are for the TransportControls
     void play();
-    void playUri(in Uri uri, in Bundle extras);
+    void playFromMediaId(String uri, in Bundle extras);
     void playFromSearch(String string, in Bundle extras);
-    void skipToTrack(long id);
+    void skipToQueueItem(long id);
     void pause();
     void stop();
     void next();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index d7baaa9..9641f83 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -173,7 +173,7 @@
      *
      * @return The current play queue or null.
      */
-    public @Nullable List<MediaSession.Item> getQueue() {
+    public @Nullable List<MediaSession.QueueItem> getQueue() {
         try {
             ParceledListSlice queue = mSessionBinder.getQueue();
             if (queue != null) {
@@ -538,9 +538,9 @@
          * @param queue A list of items in the current play queue. It should
          *            include the currently playing item as well as previous and
          *            upcoming items if applicable.
-         * @see MediaSession.Item
+         * @see MediaSession.QueueItem
          */
-        public void onQueueChanged(@Nullable List<MediaSession.Item> queue) {
+        public void onQueueChanged(@Nullable List<MediaSession.QueueItem> queue) {
         }
 
         /**
@@ -594,18 +594,19 @@
         /**
          * Request that the player start playback for a specific {@link Uri}.
          *
-         * @param uri The uri of the requested media.
+         * @param mediaId The uri of the requested media.
          * @param extras Optional extras that can include extra information about the media item
          *               to be played.
          */
-        public void playUri(Uri uri, Bundle extras) {
-            if (uri == null) {
-                throw new IllegalArgumentException("You must specify a non-null Uri for playUri.");
+        public void playFromMediaId(String mediaId, Bundle extras) {
+            if (TextUtils.isEmpty(mediaId)) {
+                throw new IllegalArgumentException(
+                        "You must specify a non-empty String for playFromMediaId.");
             }
             try {
-                mSessionBinder.playUri(uri, extras);
+                mSessionBinder.playFromMediaId(mediaId, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + uri + ").", e);
+                Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
             }
         }
 
@@ -631,9 +632,9 @@
          * Play an item with a specific id in the play queue. If you specify an
          * id that is not in the play queue, the behavior is undefined.
          */
-        public void skipToItem(long id) {
+        public void skipToQueueItem(long id) {
             try {
-                mSessionBinder.skipToTrack(id);
+                mSessionBinder.skipToQueueItem(id);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
@@ -904,7 +905,7 @@
 
         @Override
         public void onQueueChanged(ParceledListSlice parceledQueue) {
-            List<MediaSession.Item> queue = parceledQueue.getList();
+            List<MediaSession.QueueItem> queue = parceledQueue.getList();
             MediaController controller = mController.get();
             if (controller != null) {
                 controller.postMessage(MSG_UPDATE_QUEUE, queue, null);
@@ -960,7 +961,7 @@
                     mCallback.onMetadataChanged((MediaMetadata) msg.obj);
                     break;
                 case MSG_UPDATE_QUEUE:
-                    mCallback.onQueueChanged((List<MediaSession.Item>) msg.obj);
+                    mCallback.onQueueChanged((List<MediaSession.QueueItem>) msg.obj);
                     break;
                 case MSG_UPDATE_QUEUE_TITLE:
                     mCallback.onQueueTitleChanged((CharSequence) msg.obj);
diff --git a/media/java/android/media/session/MediaSession.aidl b/media/java/android/media/session/MediaSession.aidl
index 0ad58c4..f657cef 100644
--- a/media/java/android/media/session/MediaSession.aidl
+++ b/media/java/android/media/session/MediaSession.aidl
@@ -16,4 +16,4 @@
 package android.media.session;
 
 parcelable MediaSession.Token;
-parcelable MediaSession.Track;
\ No newline at end of file
+parcelable MediaSession.QueueItem;
\ No newline at end of file
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 1670097..711831b 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.media.AudioAttributes;
+import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -38,6 +39,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
+import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -180,18 +182,26 @@
      * @param handler The handler that events should be posted on.
      */
     public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
-        if (callback == null) {
-            mCallback = null;
-            return;
-        }
         synchronized (mLock) {
-            if (mCallback != null && mCallback.mCallback == callback) {
-                Log.w(TAG, "Tried to set same callback, ignoring");
+            if (callback == null) {
+                if (mCallback != null) {
+                    mCallback.mCallback.mSession = null;
+                }
+                mCallback = null;
                 return;
             }
+            if (mCallback != null) {
+                if (mCallback.mCallback == callback) {
+                    Log.w(TAG, "Tried to set same callback, ignoring");
+                    return;
+                }
+                // We're changing callbacks, clear the session from the old one.
+                mCallback.mCallback.mSession = null;
+            }
             if (handler == null) {
                 handler = new Handler();
             }
+            callback.mSession = this;
             CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(),
                     callback);
             mCallback = msgHandler;
@@ -418,9 +428,9 @@
      *
      * @param queue A list of items in the play queue.
      */
-    public void setQueue(@Nullable List<Item> queue) {
+    public void setQueue(@Nullable List<QueueItem> queue) {
         try {
-            mBinder.setQueue(new ParceledListSlice<Item>(queue));
+            mBinder.setQueue(new ParceledListSlice<QueueItem>(queue));
         } catch (RemoteException e) {
             Log.wtf("Dead object in setQueue.", e);
         }
@@ -478,8 +488,8 @@
         postToCallback(CallbackMessageHandler.MSG_PLAY);
     }
 
-    private void dispatchPlayUri(Uri uri, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
+    private void dispatchPlayFromMediaId(String mediaId, Bundle extras) {
+        postToCallback(CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras);
     }
 
     private void dispatchPlayFromSearch(String query, Bundle extras) {
@@ -744,9 +754,10 @@
         }
 
         /**
-         * Override to handle requests to play a specific {@link Uri}.
+         * Override to handle requests to play a specific mediaId that was
+         * provided by your app's {@link MediaBrowserService}.
          */
-        public void onPlayUri(Uri uri, Bundle extras) {
+        public void onPlayFromMediaId(String mediaId, Bundle extras) {
         }
 
         /**
@@ -759,7 +770,7 @@
          * Override to handle requests to play an item with a given id from the
          * play queue.
          */
-        public void onSkipToItem(long id) {
+        public void onSkipToQueueItem(long id) {
         }
 
         /**
@@ -824,10 +835,6 @@
          */
         public void onCustomAction(@NonNull String action, @Nullable Bundle extras) {
         }
-
-        private void setSession(MediaSession session) {
-            mSession = session;
-        }
     }
 
     /**
@@ -872,10 +879,10 @@
         }
 
         @Override
-        public void onPlayUri(Uri uri, Bundle extras) {
+        public void onPlayFromMediaId(String mediaId, Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPlayUri(uri, extras);
+                session.dispatchPlayFromMediaId(mediaId, extras);
             }
         }
 
@@ -990,125 +997,59 @@
     }
 
     /**
-     * A single item that is part of the play queue. It contains information
-     * necessary to display a single item in the queue.
+     * A single item that is part of the play queue. It contains a description
+     * of the item and its id in the queue.
      */
-    public static final class Item implements Parcelable {
+    public static final class QueueItem implements Parcelable {
         /**
          * This id is reserved. No items can be explicitly asigned this id.
          */
         public static final int UNKNOWN_ID = -1;
 
-        private final MediaMetadata mMetadata;
+        private final MediaDescription mDescription;
         private final long mId;
-        private final Uri mUri;
-        private final Bundle mExtras;
 
         /**
-         * Create a new {@link MediaSession.Item}.
+         * Create a new {@link MediaSession.QueueItem}.
          *
-         * @param metadata The metadata for this item.
+         * @param description The {@link MediaDescription} for this item.
          * @param id An identifier for this item. It must be unique within the
-         *            play queue.
-         * @param uri The uri for this item.
-         * @param extras A bundle of extras that can be used to add extra
-         *            information about this item.
+         *            play queue and cannot be {@link #UNKNOWN_ID}.
          */
-        private Item(MediaMetadata metadata, long id, Uri uri, Bundle extras) {
-            mMetadata = metadata;
+        public QueueItem(MediaDescription description, long id) {
+            if (description == null) {
+                throw new IllegalArgumentException("Description cannot be null.");
+            }
+            if (id == UNKNOWN_ID) {
+                throw new IllegalArgumentException("Id cannot be QueueItem.UNKNOWN_ID");
+            }
+            mDescription = description;
             mId = id;
-            mUri = uri;
-            mExtras = extras;
         }
 
-        private Item(Parcel in) {
-            mMetadata = MediaMetadata.CREATOR.createFromParcel(in);
+        private QueueItem(Parcel in) {
+            mDescription = MediaDescription.CREATOR.createFromParcel(in);
             mId = in.readLong();
-            mUri = Uri.CREATOR.createFromParcel(in);
-            mExtras = in.readBundle();
         }
 
         /**
-         * Get the metadata for this item.
+         * Get the description for this item.
          */
-        public MediaMetadata getMetadata() {
-            return mMetadata;
+        public MediaDescription getDescription() {
+            return mDescription;
         }
 
         /**
-         * Get the id for this item.
+         * Get the queue id for this item.
          */
-        public long getId() {
+        public long getQueueId() {
             return mId;
         }
 
-        /**
-         * Get the Uri for this item.
-         */
-        public Uri getUri() {
-            return mUri;
-        }
-
-        /**
-         * Get the extras for this item.
-         */
-        public Bundle getExtras() {
-            return mExtras;
-        }
-
-        /**
-         * Builder for {@link MediaSession.Item} objects.
-         */
-        public static final class Builder {
-            private final MediaMetadata mMetadata;
-            private final long mId;
-            private final Uri mUri;
-
-            private Bundle mExtras;
-
-            /**
-             * Create a builder with the metadata, id, and uri already set.
-             */
-            public Builder(MediaMetadata metadata, long id, Uri uri) {
-                if (metadata == null) {
-                    throw new IllegalArgumentException(
-                            "You must specify a non-null MediaMetadata to build an Item.");
-                }
-                if (uri == null) {
-                    throw new IllegalArgumentException(
-                            "You must specify a non-null Uri to build an Item.");
-                }
-                if (id == UNKNOWN_ID) {
-                    throw new IllegalArgumentException(
-                            "You must specify an id other than UNKNOWN_ID to build an Item.");
-                }
-                mMetadata = metadata;
-                mId = id;
-                mUri = uri;
-            }
-
-            /**
-             * Set optional extras for the item.
-             */
-            public MediaSession.Item.Builder setExtras(Bundle extras) {
-                mExtras = extras;
-                return this;
-            }
-
-            /**
-             * Create the {@link Item}.
-             */
-            public MediaSession.Item build() {
-                return new MediaSession.Item(mMetadata, mId, mUri, mExtras);
-            }
-        }
-
         @Override
         public void writeToParcel(Parcel dest, int flags) {
-            mMetadata.writeToParcel(dest, flags);
+            mDescription.writeToParcel(dest, flags);
             dest.writeLong(mId);
-            mUri.writeToParcel(dest, flags);
-            dest.writeBundle(mExtras);
         }
 
         @Override
@@ -1116,28 +1057,24 @@
             return 0;
         }
 
-        public static final Creator<MediaSession.Item> CREATOR
-                = new Creator<MediaSession.Item>() {
+        public static final Creator<MediaSession.QueueItem> CREATOR = new Creator<MediaSession.QueueItem>() {
 
             @Override
-            public MediaSession.Item createFromParcel(Parcel p) {
-                return new MediaSession.Item(p);
+            public MediaSession.QueueItem createFromParcel(Parcel p) {
+                return new MediaSession.QueueItem(p);
             }
 
             @Override
-            public MediaSession.Item[] newArray(int size) {
-                return new MediaSession.Item[size];
+            public MediaSession.QueueItem[] newArray(int size) {
+                return new MediaSession.QueueItem[size];
             }
         };
 
         @Override
         public String toString() {
-            return "MediaSession.Item {" +
-                    "Metadata=" + mMetadata +
-                    ", Id=" + mId +
-                    ", Uri=" + mUri +
-                    ", Extras=" + mExtras +
-                    " }";
+            return "MediaSession.QueueItem {" +
+                    "Description=" + mDescription +
+                    ", Id=" + mId + " }";
         }
     }
 
@@ -1156,7 +1093,7 @@
     private class CallbackMessageHandler extends Handler {
 
         private static final int MSG_PLAY = 1;
-        private static final int MSG_PLAY_URI = 2;
+        private static final int MSG_PLAY_MEDIA_ID = 2;
         private static final int MSG_PLAY_SEARCH = 3;
         private static final int MSG_SKIP_TO_ITEM = 4;
         private static final int MSG_PAUSE = 5;
@@ -1202,14 +1139,14 @@
                 case MSG_PLAY:
                     mCallback.onPlay();
                     break;
-                case MSG_PLAY_URI:
-                    mCallback.onPlayUri((Uri) msg.obj, msg.getData());
+                case MSG_PLAY_MEDIA_ID:
+                    mCallback.onPlayFromMediaId((String) msg.obj, msg.getData());
                     break;
                 case MSG_PLAY_SEARCH:
                     mCallback.onPlayFromSearch((String) msg.obj, msg.getData());
                     break;
                 case MSG_SKIP_TO_ITEM:
-                    mCallback.onSkipToItem((Long) msg.obj);
+                    mCallback.onSkipToQueueItem((Long) msg.obj);
                 case MSG_PAUSE:
                     mCallback.onPause();
                     break;
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 2ca97dd..267d1ff 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -36,95 +36,95 @@
     private static final String TAG = "PlaybackState";
 
     /**
-     * Indicates this performer supports the stop command.
+     * Indicates this session supports the stop command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_STOP = 1 << 0;
 
     /**
-     * Indicates this performer supports the pause command.
+     * Indicates this session supports the pause command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_PAUSE = 1 << 1;
 
     /**
-     * Indicates this performer supports the play command.
+     * Indicates this session supports the play command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_PLAY = 1 << 2;
 
     /**
-     * Indicates this performer supports the rewind command.
+     * Indicates this session supports the rewind command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_REWIND = 1 << 3;
 
     /**
-     * Indicates this performer supports the previous command.
+     * Indicates this session supports the previous command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4;
 
     /**
-     * Indicates this performer supports the next command.
+     * Indicates this session supports the next command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_SKIP_TO_NEXT = 1 << 5;
 
     /**
-     * Indicates this performer supports the fast forward command.
+     * Indicates this session supports the fast forward command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_FAST_FORWARD = 1 << 6;
 
     /**
-     * Indicates this performer supports the set rating command.
+     * Indicates this session supports the set rating command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_SET_RATING = 1 << 7;
 
     /**
-     * Indicates this performer supports the seek to command.
+     * Indicates this session supports the seek to command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_SEEK_TO = 1 << 8;
 
     /**
-     * Indicates this performer supports the play/pause toggle command.
+     * Indicates this session supports the play/pause toggle command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_PLAY_PAUSE = 1 << 9;
 
     /**
-     * Indicates this performer supports the play from uri command.
+     * Indicates this session supports the play from media id command.
      *
      * @see Builder#setActions(long)
      */
-    public static final long ACTION_PLAY_URI = 1 << 10;
+    public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10;
 
     /**
-     * Indicates this performer supports the play from search command.
+     * Indicates this session supports the play from search command.
      *
      * @see Builder#setActions(long)
      */
     public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11;
 
     /**
-     * Indicates this performer supports the skip to item command.
+     * Indicates this session supports the skip to queue item command.
      *
      * @see Builder#setActions(long)
      */
-    public static final long ACTION_SKIP_TO_ITEM = 1 << 12;
+    public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12;
 
     /**
      * This is the default playback state and indicates that no media has been
@@ -211,6 +211,14 @@
     public final static int STATE_SKIPPING_TO_NEXT = 10;
 
     /**
+     * State indicating the player is currently skipping to a specific item in
+     * the queue.
+     *
+     * @see Builder#setState
+     */
+    public final static int STATE_SKIPPING_TO_QUEUE_ITEM = 11;
+
+    /**
      * Use this value for the position to indicate the position is not known.
      */
     public final static long PLAYBACK_POSITION_UNKNOWN = -1;
@@ -374,6 +382,18 @@
     }
 
     /**
+     * Get the id of the currently active item in the queue. If there is no
+     * queue or a queue is not supported by the session this will be
+     * {@link MediaSession.QueueItem#UNKNOWN_ID}.
+     *
+     * @return The id of the currently active item in the queue or
+     *         {@link MediaSession.QueueItem#UNKNOWN_ID}.
+     */
+    public long getActiveQueueItemId() {
+        return mActiveItemId;
+    }
+
+    /**
      * Get the {@link PlaybackState} state for the given
      * {@link RemoteControlClient} state.
      *
@@ -716,7 +736,7 @@
         private long mActions;
         private CharSequence mErrorMessage;
         private long mUpdateTime;
-        private long mActiveItemId = MediaSession.Item.UNKNOWN_ID;
+        private long mActiveItemId = MediaSession.QueueItem.UNKNOWN_ID;
 
         /**
          * Creates an initially empty state builder.
@@ -904,12 +924,12 @@
 
         /**
          * Set the active item in the play queue by specifying its id. The
-         * default value is {@link MediaSession.Item#UNKNOWN_ID}
+         * default value is {@link MediaSession.QueueItem#UNKNOWN_ID}
          *
          * @param id The id of the active item.
          * @return this
          */
-        public Builder setActiveItem(long id) {
+        public Builder setActiveQueueItemId(long id) {
             mActiveItemId = id;
             return this;
         }
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 20b8e7c..6ca794e 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -22,6 +22,7 @@
 import android.media.tv.ITvInputHardware;
 import android.media.tv.ITvInputHardwareCallback;
 import android.media.tv.ITvInputManagerCallback;
+import android.media.tv.TvContentRatingSystemInfo;
 import android.media.tv.TvInputHardwareInfo;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvStreamConfig;
@@ -38,7 +39,7 @@
     List<TvInputInfo> getTvInputList(int userId);
     TvInputInfo getTvInputInfo(in String inputId, int userId);
 
-    List<Uri> getTvContentRatingSystemXmls(int userId);
+    List<TvContentRatingSystemInfo> getTvContentRatingSystemList(int userId);
 
     void registerCallback(in ITvInputManagerCallback callback, int userId);
     void unregisterCallback(in ITvInputManagerCallback callback, int userId);
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index bbf7399..0bda2b3 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -33,10 +33,9 @@
  * {@link #createRating TvContentRating.createRating} method with valid rating system string
  * constants.
  * <p>
- * It is possible for a TV input to define its own content rating system by supplying a content
- * rating system definition XML resource (see example below) and having the
- * {@link android.R.attr#tvContentRatingDescription tvContentRatingDescription} attribute in
- * {@link TvInputService#SERVICE_META_DATA} of the TV input point to it.
+ * It is possible for an application to define its own content rating system by supplying a content
+ * rating system definition XML resource (see example below) and declaring a broadcast receiver that
+ * filters {@link TvInputManager#ACTION_QUERY_CONTENT_RATING_SYSTEMS} in its manifest.
  * </p>
  * <h3> Example: Rating system definition for the TV Parental Guidelines</h3>
  * The following XML example shows how the TV Parental Guidelines in the United States can be
diff --git a/media/java/android/media/tv/TvContentRatingSystemInfo.aidl b/media/java/android/media/tv/TvContentRatingSystemInfo.aidl
new file mode 100644
index 0000000..957be62
--- /dev/null
+++ b/media/java/android/media/tv/TvContentRatingSystemInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.media.tv;
+
+parcelable TvContentRatingSystemInfo;
\ No newline at end of file
diff --git a/media/java/android/media/tv/TvContentRatingSystemInfo.java b/media/java/android/media/tv/TvContentRatingSystemInfo.java
new file mode 100644
index 0000000..f2e5b08c
--- /dev/null
+++ b/media/java/android/media/tv/TvContentRatingSystemInfo.java
@@ -0,0 +1,111 @@
+/*
+ * 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.media.tv;
+
+import android.annotation.SystemApi;
+import android.content.ContentResolver;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * TvContentRatingSystemInfo class provides information about a specific TV content rating system
+ * defined either by a system app or by a third-party app.
+ *
+ * @hide
+ */
+@SystemApi
+public final class TvContentRatingSystemInfo implements Parcelable {
+    private final Uri mXmlUri;
+
+    private final ApplicationInfo mApplicationInfo;
+
+    /**
+     * Creates a TvContentRatingSystemInfo object with given resource ID and receiver info.
+     *
+     * @param xmlResourceId The ID of an XML resource whose root element is
+     *            <code> &lt;rating-system-definitions&gt;</code>
+     * @param applicationInfo Information about the application that provides the TV content rating
+     *            system definition.
+     */
+    public static final TvContentRatingSystemInfo createTvContentRatingSystemInfo(int xmlResourceId,
+            ApplicationInfo applicationInfo) {
+        Uri uri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                .authority(applicationInfo.packageName)
+                .appendPath(String.valueOf(xmlResourceId))
+                .build();
+        return new TvContentRatingSystemInfo(uri, applicationInfo);
+    }
+
+    private TvContentRatingSystemInfo(Uri xmlUri, ApplicationInfo applicationInfo) {
+        mXmlUri = xmlUri;
+        mApplicationInfo = applicationInfo;
+    }
+
+    /**
+     * Returns {@code true} if the TV content rating system is defined by a system app,
+     * {@code false} otherwise.
+     */
+    public final boolean isSystemDefined() {
+        return (mApplicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    /**
+     * Returns the URI to the XML resource that defines the TV content rating system.
+     *
+     * TODO: Remove. Instead, parse the XML resource and provide an interface to directly access
+     * parsed information.
+     */
+    public final Uri getXmlUri() {
+        return mXmlUri;
+    }
+
+    /**
+     * Used to make this class parcelable.
+     * @hide
+     */
+    public static final Parcelable.Creator<TvContentRatingSystemInfo> CREATOR =
+            new Parcelable.Creator<TvContentRatingSystemInfo>() {
+        @Override
+        public TvContentRatingSystemInfo createFromParcel(Parcel in) {
+            return new TvContentRatingSystemInfo(in);
+        }
+
+        @Override
+        public TvContentRatingSystemInfo[] newArray(int size) {
+            return new TvContentRatingSystemInfo[size];
+        }
+    };
+
+    private TvContentRatingSystemInfo(Parcel in) {
+        mXmlUri = in.readParcelable(null);
+        mApplicationInfo = in.readParcelable(null);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mXmlUri, flags);
+        dest.writeParcelable(mApplicationInfo, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 00c7ad4..7f1c304 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -680,7 +680,7 @@
          * <p>
          * A value of 1 indicates the channel is included in the channel list that applications use
          * to browse channels, a value of 0 indicates the channel is not included in the list. If
-         * not specified, this value is set to 1 (browsable) by default.
+         * not specified, this value is set to 0 (not browsable) by default.
          * </p><p>
          * Type: INTEGER (boolean)
          * </p>
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 106e1dc..00183bb 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -18,7 +18,6 @@
 
 import android.annotation.SystemApi;
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -125,7 +124,6 @@
     private String mLabel;
     private Uri mIconUri;
     private boolean mIsConnectedToHdmiSwitch;
-    private Uri mRatingSystemXmlUri;
 
     static {
         sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_OTHER_HARDWARE,
@@ -245,19 +243,6 @@
                 Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
                         + si.name);
             }
-            int tvContentRatingDescription = sa.getResourceId(
-                    com.android.internal.R.styleable.TvInputService_tvContentRatingDescription, -1);
-            if (tvContentRatingDescription != -1) {
-                input.mRatingSystemXmlUri = new Uri.Builder()
-                        .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                        .authority(si.packageName)
-                        .appendPath(Integer.toString(tvContentRatingDescription))
-                        .build();
-                if (DEBUG) {
-                    Log.d(TAG, "Content rating xml loaded. [" + tvContentRatingDescription
-                            + "] for " + si.name);
-                }
-            }
             sa.recycle();
 
             input.mLabel = label;
@@ -367,15 +352,6 @@
     }
 
     /**
-     * Returns the resource uri for the rating system xml of this TV input service.
-     * @hide
-     */
-    @SystemApi
-    public Uri getRatingSystemXmlUri() {
-        return mRatingSystemXmlUri;
-    }
-
-    /**
      * Returns {@code true} if this TV input is pass-though which does not have any real channels
      * in TvProvider. {@code false} otherwise.
      *
@@ -508,7 +484,6 @@
         dest.writeParcelable(mIconUri, flags);
         dest.writeString(mLabel);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
-        dest.writeParcelable(mRatingSystemXmlUri, flags);
     }
 
     private Drawable loadDefaultIcon(Context context) {
@@ -581,7 +556,6 @@
         mIconUri = in.readParcelable(null);
         mLabel = in.readString();
         mIsConnectedToHdmiSwitch = in.readByte() == 1 ? true : false;
-        mRatingSystemXmlUri = in.readParcelable(null);
     }
 
     /**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 13937e2..6d1f0e4 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -101,14 +101,58 @@
      * {@link #isRatingBlocked}.
      */
     public static final String ACTION_BLOCKED_RATINGS_CHANGED =
-            "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
+            "android.media.tv.TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED";
 
     /**
      * Broadcast intent action when the parental controls enabled state changes. For use with the
      * {@link #isParentalControlsEnabled}.
      */
     public static final String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED =
-            "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+            "android.media.tv.TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED";
+
+    /**
+     * Broadcast intent action used to query available content rating systems.
+     * <p>
+     * The TV input manager service locates available content rating systems by querying broadcast
+     * receivers that are registered for this action. An application can offer additional content
+     * rating systems to the user by declaring a suitable broadcast receiver in its manifest.
+     * </p><p>
+     * Here is an example broadcast receiver declaration that an application might include in its
+     * AndroidManifest.xml to advertise custom content rating systems. The meta-data specifies a
+     * resource that contains a description of each content rating system that is provided by the
+     * application.
+     * <p><pre class="prettyprint">
+     * {@literal
+     * <receiver android:name=".TvInputReceiver">
+     *     <intent-filter>
+     *         <action android:name=
+     *                 "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS" />
+     *     </intent-filter>
+     *     <meta-data
+     *             android:name="android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS"
+     *             android:resource="@xml/tv_content_rating_systems" />
+     * </receiver>}</pre></p>
+     * In the above example, the <code>@xml/tv_content_rating_systems</code> resource refers to an
+     * XML resource whose root element is <code>&lt;rating-system-definitions&gt;</code> that
+     * contains zero or more <code>&lt;rating-system-definition&gt;</code> elements. Each <code>
+     * &lt;rating-system-definition&gt;</code> element specifies the ratings, sub-ratings and rating
+     * orders of a particular content rating system.
+     * </p>
+     *
+     * @see TvContentRating
+     */
+    public static final String ACTION_QUERY_CONTENT_RATING_SYSTEMS =
+            "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS";
+
+    /**
+     * Content rating systems metadata associated with {@link #ACTION_QUERY_CONTENT_RATING_SYSTEMS}.
+     * <p>
+     * Specifies the resource ID of an XML resource that describes the content rating systems that
+     * are provided by the application.
+     * </p>
+     */
+    public static final String META_DATA_CONTENT_RATING_SYSTEMS =
+            "android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS";
 
     private final ITvInputManager mService;
 
@@ -863,13 +907,13 @@
     }
 
     /**
-     * Returns the list of xml resource uris for TV content rating systems.
+     * Returns the list of all TV content rating systems defined.
      * @hide
      */
     @SystemApi
-    public List<Uri> getTvContentRatingSystemXmls() {
+    public List<TvContentRatingSystemInfo> getTvContentRatingSystemList() {
         try {
-            return mService.getTvContentRatingSystemXmls(mUserId);
+            return mService.getTvContentRatingSystemList(mUserId);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
diff --git a/media/java/android/media/browse/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
similarity index 76%
rename from media/java/android/media/browse/IMediaBrowserService.aidl
rename to media/java/android/service/media/IMediaBrowserService.aidl
index 8acd724..2631ddd 100644
--- a/media/java/android/media/browse/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -1,9 +1,9 @@
 // Copyright 2014 Google Inc. All Rights Reserved.
 
-package android.media.browse;
+package android.service.media;
 
 import android.content.res.Configuration;
-import android.media.browse.IMediaBrowserServiceCallbacks;
+import android.service.media.IMediaBrowserServiceCallbacks;
 import android.net.Uri;
 import android.os.Bundle;
 
@@ -18,6 +18,4 @@
 
     void addSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks);
     void removeSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks);
-    void loadIcon(in int seqNum, in Uri uri, int width, int height,
-            IMediaBrowserServiceCallbacks callbacks);
 }
\ No newline at end of file
diff --git a/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
similarity index 91%
rename from media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl
rename to media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index 06fabcc..7702a50b 100644
--- a/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -1,6 +1,6 @@
 // Copyright 2014 Google Inc. All Rights Reserved.
 
-package android.media.browse;
+package android.service.media;
 
 import android.content.pm.ParceledListSlice;
 import android.graphics.Bitmap;
@@ -24,5 +24,4 @@
     void onConnect(in Uri root, in MediaSession.Token session, in Bundle extras);
     void onConnectFailed();
     void onLoadChildren(in Uri uri, in ParceledListSlice list);
-    void onLoadIcon(int seqNum, in Bitmap bitmap);
 }
diff --git a/media/java/android/media/browse/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
similarity index 81%
rename from media/java/android/media/browse/MediaBrowserService.java
rename to media/java/android/service/media/MediaBrowserService.java
index 99126c9..4d6fd7b 100644
--- a/media/java/android/media/browse/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.browse;
+package android.service.media;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -27,6 +27,8 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.media.browse.MediaBrowser;
+import android.media.browse.MediaBrowser.MediaItem;
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.Binder;
@@ -34,6 +36,9 @@
 import android.os.IBinder;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.service.media.IMediaBrowserService;
+import android.service.media.IMediaBrowserServiceCallbacks;
+import android.service.media.IMediaBrowserService.Stub;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -264,59 +269,6 @@
                 }
             });
         }
-
-        @Override
-        public void loadIcon(final int seq, final Uri uri, final int width, final int height,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            if (uri == null) {
-                throw new IllegalStateException("loadIcon sent null list for uri " + uri);
-            }
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    // In theory we could return a result to a new connection, but in practice
-                    // the other side in MediaBrowser uses a new IMediaBrowserServiceCallbacks
-                    // object every time it calls connect(), so as long as it does that we won't
-                    // see results sent for the wrong connection.
-                    final ConnectionRecord connection = mConnections.get(callbacks.asBinder());
-                    if (connection == null) {
-                        if (DBG) {
-                            Log.d(TAG, "Not loading bitmap for invalid connection. uri=" + uri);
-                        }
-                        return;
-                    }
-
-                    final Result<Bitmap> result = new Result<Bitmap>(uri) {
-                        @Override
-                        void onResultSent(Bitmap bitmap) {
-                            if (mConnections.get(connection.callbacks.asBinder()) != connection) {
-                                if (DBG) {
-                                    Log.d(TAG, "Not sending onLoadIcon result for connection"
-                                            + " that has been disconnected. pkg=" + connection.pkg
-                                            + " uri=" + uri);
-                                }
-                                return;
-                            }
-
-                            try {
-                                callbacks.onLoadIcon(seq, bitmap);
-                            } catch (RemoteException e) {
-                                // The other side is in the process of crashing.
-                                Log.w(TAG, "RemoteException in calling onLoadIcon", e);
-                            }
-                        }
-                    };
-
-                    onLoadIcon(uri, width, height, result);
-
-                    if (!result.isDone()) {
-                        throw new IllegalStateException("onLoadIcon must call detach() or"
-                                + " sendResult() before returning for package=" + connection.pkg
-                                + " uri=" + uri);
-                    }
-                }
-            });
-        }
     }
 
     @Override
@@ -372,26 +324,7 @@
      * @return The list of children, or null if the uri is invalid.
      */
     public abstract void onLoadChildren(@NonNull Uri parentUri,
-            @NonNull Result<List<MediaBrowserItem>> result);
-
-    /**
-     * Called to get the icon of a particular media item.
-     * <p>
-     * Implementations must call result.{@link Result#sendResult result.sendResult} with the bitmap.
-     * If loading the bitmap will be an expensive operation that should be performed
-     * on another thread, result.{@link Result#detach result.detach} may be called before returning
-     * from this function, and then {@link Result#sendResult result.sendResult} called when
-     * the loading is complete.
-     *
-     * @param uri The uri of the media item.
-     * @param width The requested width of the icon in dp.
-     * @param height The requested height of the icon in dp.
-     *
-     * @return The file descriptor of the icon, which may then be loaded
-     *          using a bitmap factory, or null if the item does not have an icon.
-     */
-    public abstract void onLoadIcon(@NonNull Uri uri, int width, int height,
-            @NonNull Result<Bitmap> result);
+            @NonNull Result<List<MediaBrowser.MediaItem>> result);
 
     /**
      * Call to set the media session.
@@ -478,9 +411,11 @@
      * Callers must make sure that this connection is still connected.
      */
     private void performLoadChildren(final Uri uri, final ConnectionRecord connection) {
-        final Result<List<MediaBrowserItem>> result = new Result<List<MediaBrowserItem>>(uri) {
+        final Result<List<MediaBrowser.MediaItem>> result
+ = new Result<List<MediaBrowser.MediaItem>>(
+                uri) {
             @Override
-            void onResultSent(List<MediaBrowserItem> list) {
+            void onResultSent(List<MediaBrowser.MediaItem> list) {
                 if (list == null) {
                     throw new IllegalStateException("onLoadChildren sent null list for uri " + uri);
                 }
@@ -492,7 +427,7 @@
                     return;
                 }
 
-                final ParceledListSlice<MediaBrowserItem> pls = new ParceledListSlice(list);
+                final ParceledListSlice<MediaBrowser.MediaItem> pls = new ParceledListSlice(list);
                 try {
                     connection.callbacks.onLoadChildren(uri, pls);
                 } catch (RemoteException ex) {
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index c678ac7..0fed27e 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -263,7 +263,7 @@
 
     String8 vendorMessage;
     if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
-        vendorMessage.format("DRM vendor-defined error: %d", err);
+        vendorMessage = String8::format("DRM vendor-defined error: %d", err);
         drmMessage = vendorMessage.string();
     }
 
@@ -285,7 +285,7 @@
             if (msg == NULL) {
                 msg = drmMessage;
             } else {
-                errbuf.format("%s: %s", msg, drmMessage);
+                errbuf = String8::format("%s: %s", msg, drmMessage);
                 msg = errbuf.string();
             }
         }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index 38d7e3e..86c23c7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -25,6 +25,9 @@
 public class MediaNames {
     // A directory to hold all kinds of media files
     public static final String MEDIA_SAMPLE_POOL = "/sdcard/media_api/samples/";
+    // A file to hold all streaming URLs
+    public static final String MEDIA_STREAMING_SRC = "/sdcard/media_api/streaming.txt";
+
     // Audio files
     public static final String MP3CBR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3";
     public static final String MP3VBR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_VBR.mp3";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index e84f762..66ed933 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -42,13 +42,13 @@
 import java.util.Random;
 /**
  * Junit / Instrumentation test case for the media player api
- 
- */  
-public class CodecTest {    
+
+ */
+public class CodecTest {
     private static String TAG = "CodecTest";
     private static MediaPlayer mMediaPlayer;
     private MediaPlayer.OnPreparedListener mOnPreparedListener;
-    
+
     private static int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
     private static boolean mInitialized = false;
     private static boolean mPrepareReset = false;
@@ -66,18 +66,18 @@
     public static int mMediaInfoNotSeekableCount = 0;
     public static int mMediaInfoMetdataUpdateCount = 0;
 
-    public static String printCpuInfo(){      
+    public static String printCpuInfo(){
         String cm = "dumpsys cpuinfo";
         String cpuinfo =null;
         int ch;
         try{
             Process  p = Runtime.getRuntime().exec(cm);
-            InputStream in = p.getInputStream();        
+            InputStream in = p.getInputStream();
             StringBuffer sb = new StringBuffer(512);
-            while ( ( ch = in.read() ) != -1 ){  
-                sb.append((char) ch); 
+            while ( ( ch = in.read() ) != -1 ){
+                sb.append((char) ch);
             }
-            cpuinfo = sb.toString();      
+            cpuinfo = sb.toString();
         }catch (IOException e){
             Log.v(TAG, e.toString());
         }
@@ -90,14 +90,14 @@
         MediaPlayer mp = new MediaPlayer();
         try{
             mp.setDataSource(filePath);
-            mp.prepare(); 
+            mp.prepare();
         }catch (Exception e){
             Log.v(TAG, e.toString());
         }
         int duration = mp.getDuration();
         Log.v(TAG, "Duration " + duration);
         mp.release();
-        Log.v(TAG, "release");      
+        Log.v(TAG, "release");
         return duration;
     }
 
@@ -122,7 +122,7 @@
         }
         currentPosition = mp.getCurrentPosition();
         mp.stop();
-        mp.release();   
+        mp.release();
         Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1));
         //The currentposition should be within 10% of the sleep time
         //For the very short mp3, it should return the length instead of 10 seconds
@@ -130,11 +130,11 @@
             if (currentPosition < 1000 )
                 return true;
         }
-        if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0)) 
+        if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0))
             return true;
         else
             return false;
-    }  
+    }
 
     public static boolean seekTo(String filePath){
         Log.v(TAG, "seekTo " + filePath);
@@ -149,12 +149,12 @@
             currentPosition = mp.getCurrentPosition();
         }catch (Exception e){
             Log.v(TAG, e.getMessage());
-        }      
+        }
         mp.stop();
         mp.release();
         Log.v(TAG, "CurrentPosition = " + currentPosition);
         //The currentposition should be at least greater than the 80% of seek time
-        if ((currentPosition > MediaNames.SEEK_TIME *0.8)) 
+        if ((currentPosition > MediaNames.SEEK_TIME *0.8))
             return true;
         else
             return false;
@@ -170,7 +170,7 @@
         try{
             mp.setDataSource(filePath);
             mp.prepare();
-            duration = mp.getDuration(); 
+            duration = mp.getDuration();
             Log.v(TAG, "setLooping duration " + duration);
             mp.setLooping(true);
             mp.start();
@@ -180,14 +180,14 @@
             Thread.sleep(20000);
             t2=SystemClock.uptimeMillis();
             Log.v(TAG, "pause");
-            //Bug# 1106852 - IllegalStateException will be thrown if pause is called 
+            //Bug# 1106852 - IllegalStateException will be thrown if pause is called
             //in here
             //mp.pause();
             currentPosition = mp.getCurrentPosition();
             Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1));
         }catch (Exception e){
             Log.v(TAG, "Exception : " + e.toString());
-        }      
+        }
         mp.stop();
         mp.release();
         //The current position should be within 20% of the sleep time
@@ -196,7 +196,7 @@
             return true;
         else
             return false;
-    }  
+    }
 
     public static boolean pause(String filePath) throws Exception {
         Log.v(TAG, "pause - " + filePath);
@@ -206,7 +206,7 @@
         long t2=0;
         MediaPlayer mp = new MediaPlayer();
         mp.setDataSource(filePath);
-        mp.prepare();    
+        mp.prepare();
         int duration = mp.getDuration();
         mp.start();
         t1=SystemClock.uptimeMillis();
@@ -244,7 +244,7 @@
         mp.pause();
         mp.release();
     }
-    
+
     static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
         new MediaPlayer.OnVideoSizeChangedListener() {
             public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
@@ -258,7 +258,7 @@
     //Register the videoSizeChanged listener
     public static int videoHeight(String filePath) throws Exception {
         Log.v(TAG, "videoHeight - " + filePath);
-        int videoHeight = 0;    
+        int videoHeight = 0;
         synchronized (lock) {
             initializeMessageLooper();
             try {
@@ -286,7 +286,7 @@
         } catch (Exception e) {
             Log.e(TAG, e.getMessage());
         }
-        
+
         return videoHeight;
     }
 
@@ -321,12 +321,12 @@
             terminateMessageLooper();
         } catch (Exception e) {
             Log.e(TAG, e.getMessage());
-        }        
+        }
         return videoWidth;
     }
 
     //This also test the streaming video which may take a long
-    //time to start the playback. 
+    //time to start the playback.
     public static boolean videoSeekTo(String filePath) throws Exception {
         Log.v(TAG, "videoSeekTo - " + filePath);
         int currentPosition = 0;
@@ -392,12 +392,12 @@
         currentPosition = mp.getCurrentPosition();
         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
         mp.stop();
-        mp.release();   
+        mp.release();
         Log.v(TAG, "duration = " + duration);
         if (currentPosition < 0.9 * duration || isPlaying)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean shortMediaStop(String filePath){
@@ -419,12 +419,12 @@
         currentPosition = mp.getCurrentPosition();
         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
         mp.stop();
-        mp.release();   
+        mp.release();
         Log.v(TAG, "duration = " + duration);
         if (currentPosition > duration || isPlaying)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean playToEnd(String filePath){
@@ -449,13 +449,13 @@
         //updateDuration = mp.getDuration();
         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
         mp.stop();
-        mp.release();   
+        mp.release();
         //Log.v(TAG, "duration = " + duration);
         //Log.v(TAG, "Update duration = " + updateDuration);
         if (currentPosition > duration || isPlaying)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean seektoBeforeStart(String filePath){
@@ -478,7 +478,7 @@
         if (currentPosition < duration/2)
             return false;
         else
-            return true;        
+            return true;
     }
 
     public static boolean mediaRecorderRecord(String filePath){
@@ -499,7 +499,7 @@
             mRecorder.release();
         }catch (Exception e){
             Log.v(TAG, e.toString());
-        }  
+        }
 
         //Verify the recorded file
         MediaPlayer mp = new MediaPlayer();
@@ -540,7 +540,7 @@
             }
             Bitmap outThumbnail = mMediaMetadataRetriever.getFrameAtTime(-1);
 
-            //Verify the thumbnail 
+            //Verify the thumbnail
             Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
             outputWidth = outThumbnail.getWidth();
             outputHeight = outThumbnail.getHeight();
@@ -586,8 +586,8 @@
             return false;
     }
 
-    public static boolean prepareAsyncReset(String filePath){    
-        //preparesAsync 
+    public static boolean prepareAsyncReset(String filePath){
+        //preparesAsync
         try{
             MediaPlayer mp = new MediaPlayer();
             mp.setDataSource(filePath);
@@ -602,9 +602,9 @@
     }
 
 
-    public static boolean isLooping(String filePath) {        
+    public static boolean isLooping(String filePath) {
         MediaPlayer mp = null;
-        
+
         try {
             mp = new MediaPlayer();
             if (mp.isLooping()) {
@@ -619,7 +619,7 @@
                 Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)");
                 return false;
             }
-            
+
             mp.setLooping(false);
             if (mp.isLooping()) {
                 Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)");
@@ -659,9 +659,9 @@
 
         return true;
     }
-    
+
     /*
-     * Initializes the message looper so that the mediaPlayer object can 
+     * Initializes the message looper so that the mediaPlayer object can
      * receive the callback messages.
      */
     private static void initializeMessageLooper() {
@@ -672,10 +672,10 @@
                 // Set up a looper to be used by camera.
                 Looper.prepare();
                 Log.v(TAG, "start loopRun");
-                // Save the looper so that we can terminate this thread 
+                // Save the looper so that we can terminate this thread
                 // after we are done with it.
-                mLooper = Looper.myLooper();                
-                mMediaPlayer = new MediaPlayer();                                
+                mLooper = Looper.myLooper();
+                mMediaPlayer = new MediaPlayer();
                 synchronized (lock) {
                     mInitialized = true;
                     lock.notify();
@@ -685,7 +685,7 @@
             }
         }.start();
     }
-    
+
     /*
      * Terminates the message looper thread.
      */
@@ -693,7 +693,7 @@
         mLooper.quit();
         mMediaPlayer.release();
     }
-    
+
     static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
         public void onPrepared(MediaPlayer mp) {
             synchronized (prepareDone) {
@@ -707,14 +707,14 @@
             }
         }
     };
-   
+
     public static boolean prepareAsyncCallback(String filePath, boolean reset) throws Exception {
         //Added the PrepareReset flag which allow us to switch to different
         //test case.
         if (reset){
             mPrepareReset = true;
         }
-        
+
         synchronized (lock) {
             initializeMessageLooper();
             try {
@@ -728,18 +728,18 @@
             mMediaPlayer.setOnPreparedListener(mPreparedListener);
             mMediaPlayer.setDataSource(filePath);
             mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
-            mMediaPlayer.prepareAsync(); 
+            mMediaPlayer.prepareAsync();
             synchronized (prepareDone) {
                 try {
                     prepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
                 } catch (Exception e) {
                     Log.v(TAG, "wait was interrupted.");
                 }
-            }         
+            }
             terminateMessageLooper();
         }catch (Exception e){
             Log.v(TAG,e.getMessage());
-        }      
+        }
        return onPrepareSuccess;
     }
 
@@ -784,8 +784,12 @@
         }
     };
 
-    // For each media file, forward twice and backward once, then play to the end
     public static boolean playMediaSamples(String filePath) throws Exception {
+        return playMediaSamples(filePath, 2000);
+    }
+
+    // For each media file, forward twice and backward once, then play to the end
+    public static boolean playMediaSamples(String filePath, int buffertime) throws Exception {
         int duration = 0;
         int curPosition = 0;
         int nextPosition = 0;
@@ -822,14 +826,14 @@
             waittime = duration - mMediaPlayer.getCurrentPosition();
             synchronized(onCompletion){
                 try {
-                    onCompletion.wait(waittime + 2000);
+                    onCompletion.wait(waittime + buffertime);
                 }catch (Exception e) {
                     Log.v(TAG, "playMediaSamples are interrupted");
                     return false;
                 }
             }
             terminateMessageLooper();
-        }catch (Exception e) {
+        } catch (Exception e) {
             Log.v(TAG, "playMediaSamples:" + e.getMessage());
         }
         return onCompleteSuccess;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index b6bb578..cc50c43 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -245,7 +245,7 @@
          * android.hardware.camera2.CaptureResultExtras)
          */
         @Override
-        public void onCameraError(int errorCode, CaptureResultExtras resultExtras)
+        public void onDeviceError(int errorCode, CaptureResultExtras resultExtras)
                 throws RemoteException {
             // TODO Auto-generated method stub
 
@@ -283,7 +283,7 @@
          * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
          */
         @Override
-        public void onCameraIdle() throws RemoteException {
+        public void onDeviceIdle() throws RemoteException {
             // TODO Auto-generated method stub
 
         }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 7b2e7dd..3cae19d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -88,10 +88,10 @@
         /*
          * (non-Javadoc)
          * @see
-         * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int,
+         * android.hardware.camera2.ICameraDeviceCallbacks#onDeviceError(int,
          * android.hardware.camera2.CaptureResultExtras)
          */
-        public void onCameraError(int errorCode, CaptureResultExtras resultExtras)
+        public void onDeviceError(int errorCode, CaptureResultExtras resultExtras)
                 throws RemoteException {
             // TODO Auto-generated method stub
 
@@ -99,9 +99,9 @@
 
         /*
          * (non-Javadoc)
-         * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
+         * @see android.hardware.camera2.ICameraDeviceCallbacks#onDeviceIdle()
          */
-        public void onCameraIdle() throws RemoteException {
+        public void onDeviceIdle() throws RemoteException {
             // TODO Auto-generated method stub
 
         }
@@ -432,7 +432,7 @@
         // Cancel and make sure we eventually quiesce
         status = mCameraUser.cancelRequest(streamingId, null);
 
-        verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onCameraIdle();
+        verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle();
 
         // Submit a few capture requests
         int requestId1 = submitCameraRequest(request, /* streaming */false);
@@ -442,7 +442,7 @@
         int requestId5 = submitCameraRequest(request, /* streaming */false);
 
         // And wait for more idle
-        verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onCameraIdle();
+        verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle();
 
     }
 
@@ -472,7 +472,7 @@
         status = mCameraUser.flush(null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
-        verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onCameraIdle();
+        verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle();
 
         // Now a streaming request
         int streamingId = submitCameraRequest(request, /* streaming */true);
@@ -484,7 +484,7 @@
         status = mCameraUser.flush(null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
-        verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onCameraIdle();
+        verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle();
 
         // TODO: When errors are hooked up, count that errors + successful
         // requests equal to 5.
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStreamingStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStreamingStressTest.java
new file mode 100644
index 0000000..d92c857
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStreamingStressTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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 com.android.mediaframeworktest.stress;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaPlayerStressTestRunner;
+
+import android.os.Bundle;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import com.android.mediaframeworktest.MediaNames;
+import com.android.mediaframeworktest.functional.CodecTest;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.Writer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Junit / Instrumentation test case for the media player
+ */
+public class MediaPlayerStreamingStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private String TAG = "MediaPlayerStreamingStressTest";
+    private String mStreamingSrc;
+
+    public MediaPlayerStreamingStressTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        //Insert a 2 second before launching the test activity. This is
+        //the workaround for the race condition of requesting the updated surface.
+        Thread.sleep(2000);
+        getActivity();
+        MediaPlayerStressTestRunner mRunner = (MediaPlayerStressTestRunner)getInstrumentation();
+        Bundle arguments = mRunner.getArguments();
+        mStreamingSrc = arguments.getString("streaming-source");
+        if (mStreamingSrc == null) {
+            mStreamingSrc = MediaNames.MEDIA_STREAMING_SRC;
+        }
+        super.setUp();
+    }
+
+    private int mTotalPlaybackError = 0;
+    private int mTotalComplete = 0;
+    private int mTotalInfoUnknown = 0;
+    private int mTotalVideoTrackLagging = 0;
+    private int mTotalBadInterleaving = 0;
+    private int mTotalNotSeekable = 0;
+    private int mTotalMetaDataUpdate = 0;
+
+    //Test result output file
+    private static final String PLAYBACK_RESULT = "StreamingTestResult.txt";
+
+    private void writeTestOutput(String filename, Writer output) throws Exception{
+        output.write("URL: " + filename);
+        output.write(" Complete: " + CodecTest.onCompleteSuccess);
+        output.write(" Error: " + CodecTest.mPlaybackError);
+        output.write(" Unknown Info: " + CodecTest.mMediaInfoUnknownCount);
+        output.write(" Track Lagging: " +  CodecTest.mMediaInfoVideoTrackLaggingCount);
+        output.write(" Bad Interleaving: " + CodecTest.mMediaInfoBadInterleavingCount);
+        output.write(" Not Seekable: " + CodecTest.mMediaInfoNotSeekableCount);
+        output.write(" Info Meta data update: " + CodecTest.mMediaInfoMetdataUpdateCount);
+        output.write("\n");
+    }
+
+    private void writeTestSummary(Writer output) throws Exception{
+        output.write("Total Result:\n");
+        output.write("Total Complete: " + mTotalComplete + "\n");
+        output.write("Total Error: " + mTotalPlaybackError + "\n");
+        output.write("Total Unknown Info: " + mTotalInfoUnknown + "\n");
+        output.write("Total Track Lagging: " + mTotalVideoTrackLagging + "\n" );
+        output.write("Total Bad Interleaving: " + mTotalBadInterleaving + "\n");
+        output.write("Total Not Seekable: " + mTotalNotSeekable + "\n");
+        output.write("Total Info Meta data update: " + mTotalMetaDataUpdate + "\n");
+        output.write("\n");
+    }
+
+    private void updateTestResult(){
+        if (CodecTest.onCompleteSuccess){
+            mTotalComplete++;
+        }
+        else if (CodecTest.mPlaybackError){
+            mTotalPlaybackError++;
+        }
+        mTotalInfoUnknown += CodecTest.mMediaInfoUnknownCount;
+        mTotalVideoTrackLagging += CodecTest.mMediaInfoVideoTrackLaggingCount;
+        mTotalBadInterleaving += CodecTest.mMediaInfoBadInterleavingCount;
+        mTotalNotSeekable += CodecTest.mMediaInfoNotSeekableCount;
+        mTotalMetaDataUpdate += CodecTest.mMediaInfoMetdataUpdateCount;
+    }
+
+    //Test that will start the playback for all the videos
+    //under the samples folder
+    @LargeTest
+    public void testVideoPlayback() throws Exception {
+        String fileWithError = "Filename:\n";
+        File playbackOutput = new File(Environment.getExternalStorageDirectory(), PLAYBACK_RESULT);
+        Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
+
+        boolean testResult = true;
+        // load directory files
+        boolean onCompleteSuccess = false;
+
+
+        Log.i(TAG, "Streaming src file: " + mStreamingSrc);
+        //TODO: add try catch
+
+        File f = new File(mStreamingSrc);
+        BufferedReader br = new BufferedReader(new FileReader(f));
+        List<String> urls = new ArrayList<String>();
+        String line;
+        while ((line = br.readLine()) != null) {
+           urls.add(line.trim());
+        }
+        br.close();
+        if (urls == null) {
+            Log.v("MediaPlayerStreamingTest:testVideoPlayback", "no url found");
+            return;
+        } else {
+            for (int i = 0; i < urls.size(); i++) {
+                //Get url
+                String filename = urls.get(i);
+                onCompleteSuccess =
+                    CodecTest.playMediaSamples(filename, 60000);
+                if (!onCompleteSuccess){
+                    //Don't fail the test right away, print out the failure file.
+                    fileWithError += filename + '\n';
+                    Log.v(TAG, "Failure File : " + fileWithError);
+                    testResult = false;
+                }
+                Thread.sleep(3000);
+                //Write test result to an output file
+                writeTestOutput(filename,output);
+                //Get the summary
+                updateTestResult();
+            }
+            writeTestSummary(output);
+            output.close();
+            assertTrue("testMediaSamples", testResult);
+       }
+    }
+}
diff --git a/packages/BackupRestoreConfirmation/res/values-af/strings.xml b/packages/BackupRestoreConfirmation/res/values-af/strings.xml
index c2b7857..06a1af8 100644
--- a/packages/BackupRestoreConfirmation/res/values-af/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-af/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Voer jou toestelenkripsie-wagwoord hier onder in. Dit sal ook gebruik word om die rugsteunargief te enkripteer."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Voer asb. \'n wagwoord in om te gebruik vir enkripsie van die volle rugsteundata. As dit leeg gelaat word, sal jou huidige rugsteunwagwoord gebruik word:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"As jy die volle rugsteundata wil enkripteer, voer \'n wagwoord hieronder in:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Omdat jou toestel geënkripteer is, word daar van jou vereis om jou rugsteun te enkripteer. Voer \'n wagwoord hieronder in:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"As die hersteldata geïnkripteer  word, voer asb. die wagwoord hieronder in:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Rugsteun begin tans..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Rugsteun klaar"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml b/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml
index 1578e2f..440cb64 100644
--- a/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"দয়া করে নীচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাকআপ সংরক্ষণাগার এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷"</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে দয়া করে একটি পাসওয়ার্ড লিখুন৷ যদি এটি খালি রেখে দেওয়া হয় তবে আপনার বর্তমান ব্যাকআপ পাসওয়ার্ডটি ব্যবহার করা হবে:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নীচে একটি পাসওয়ার্ড লিখুন:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নীচে একটি পাসওয়ার্ড দিন:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"যদি পুনরুদ্ধার করা ডেটা এনক্রিপ্ট করা থাকে, তবে দয়া করে নীচে পাসওয়ার্ডটি লিখুন:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"ব্যাকআপ নেওয়া শুরু হয়েছে..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"ব্যাকআপ নেওয়া সম্পূর্ণ হয়েছে"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-de/strings.xml b/packages/BackupRestoreConfirmation/res/values-de/strings.xml
index 0977d03..a2e24e7 100644
--- a/packages/BackupRestoreConfirmation/res/values-de/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-de/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Geben Sie Ihr Passwort zur Geräteverschlüsselung unten ein. Damit wird auch das Sicherungsarchiv verschlüsselt."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Geben Sie ein Passwort für die Verschlüsselung der vollständigen Sicherungsdaten ein. Wenn Sie dieses Feld leer lassen, wird Ihr aktuelles Sicherungspasswort verwendet:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Wenn Sie die gesamten Sicherungsdaten verschlüsseln möchten, geben Sie unten ein Passwort ein:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Da Ihr Gerät verschlüsselt ist, muss auch die Sicherung verschlüsselt werden. Geben Sie unten ein Passwort ein:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Geben Sie das Passwort unten ein, wenn die Daten für die Wiederherstellung verschlüsselt sind:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Sicherung wird gestartet..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Sicherung abgeschlossen"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-el/strings.xml b/packages/BackupRestoreConfirmation/res/values-el/strings.xml
index 057108d..481ad3e 100644
--- a/packages/BackupRestoreConfirmation/res/values-el/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-el/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Εισαγάγετε τον κωδικό πρόσβασης για την κρυπτογράφηση συσκευής παρακάτω. Ο κωδικός αυτός θα χρησιμοποιηθεί και για την κρυπτογράφηση του αρχείου αντιγράφων ασφαλείας."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Εισαγάγετε έναν κωδικό πρόσβασης για χρήση για την κωδικοποίηση του πλήρους αντιγράφου ασφαλείας δεδομένων. Αν μείνει κενό, θα χρησιμοποιηθεί ο τρέχων κωδικός σας πρόσβασης:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Αν θέλετε να κρυπτογραφήσετε τα πλήρη δεδομένα αντιγράφων ασφαλείας, πληκτρολογήστε έναν κωδικό πρόσβασης παρακάτω:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Δεδομένου ότι η συσκευή σας είναι κρυπτογραφημένη, θα πρέπει να κρυπτογραφήσετε τα αντίγραφα ασφαλείας σας. Εισαγάγετε τον κωδικό παρακάτω:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Εάν η επαναφορά των δεδομένων είναι κρυπτογραφημένη, εισάγετε τον κωδικό πρόσβασης παρακάτω:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Έναρξη διαδικασίας δημιουργίας αντιγράφου ασφαλείας..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Ολοκληρώθηκε η διαδικασία δημιουργίας αντιγράφου ασφαλείας"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml
index e2bdeda..badad60 100644
--- a/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml
index e2bdeda..badad60 100644
--- a/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-es/strings.xml b/packages/BackupRestoreConfirmation/res/values-es/strings.xml
index e5cafe7..01f7cf7 100644
--- a/packages/BackupRestoreConfirmation/res/values-es/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-es/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduce a continuación la contraseña de encriptación del dispositivo. Esta contraseña se usará también para encriptar el archivo de copia de seguridad."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduce la contraseña que quieras usar para cifrar los datos de la copia de seguridad completa. Si dejas este campo en blanco, se usará tu contraseña de copia de seguridad actual:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Si quieres cifrar los datos de la copia de seguridad completa, introduce la contraseña a continuación:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Tu dispositivo está encriptado, por lo que debes encriptar tu copia de seguridad. Introduce una contraseña a continuación:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Si los datos de restauración están cifrados, introduce la contraseña a continuación:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Iniciando copia de seguridad..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Copia de seguridad finalizada"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-eu-rES/strings.xml b/packages/BackupRestoreConfirmation/res/values-eu-rES/strings.xml
index 2c35697..ca89aa6 100644
--- a/packages/BackupRestoreConfirmation/res/values-eu-rES/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-eu-rES/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Idatzi gailua enkriptatzeko pasahitza behean. Babeskopiaren artxiboa enkriptatzeko ere erabiliko da."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Idatzi babeskopia osoaren datuak enkriptatzeko erabili nahi duzun pasahitza. Eremua hutsik uzten baduzu, babeskopien uneko pasahitza erabiliko da:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Babeskopia osoko datuak enkriptatu nahi badituzu, idatzi pasahitza behean:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Gailua enkriptatuta daukazunez, babeskopiak ere enkriptatu egin behar dituzu. Idatzi pasahitza hemen:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Leheneratze-datuak enkriptatuta badaude, idatzi pasahitza behean:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Babeskopia egiten hasten…"</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Babeskopia egin da"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
index ae9361d..4c16374a 100644
--- a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"لطفاً گذرواژه رمزگذاری دستگاه خود را در زیر وارد کنید. این برای رمزگذاری بایگانی پشتیبان نیز مورد استفاده قرار می‌گیرد."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"لطفاً یک گذرواژه برای رمزگذاری داده‌های کامل نسخهٔ پشتیبانی وارد کنید. اگر این خالی بماند، گذرواژه فعلی نسخهٔ پشتیبان مورد استفاده قرار خواهد گرفت:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"اگر می‌خواهید تمام نسخه پشتیبانی داده را رمزدار کنید، یک گذرواژه در زیر وارد کنید:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"چون دستگاه‌تان رمز‌گذاری شده است، باید نسخه پشتیبان خودتان را رمزگذاری کنید. لطفاً گذرواژه‌ای را در زیر وارد کنید:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"اگر داده بازیابی شده رمزگذاری شده است، لطفاً گذرواژه را در زیر وارد کنید:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"شروع پشتیبان‌گیری..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"پشتیبان‌گیری پایان یافت"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-gl-rES/strings.xml b/packages/BackupRestoreConfirmation/res/values-gl-rES/strings.xml
index a6163d1..c973a31 100644
--- a/packages/BackupRestoreConfirmation/res/values-gl-rES/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-gl-rES/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Insire o contrasinal de encriptación do dispositivo a continuación. Tamén se usará para encriptar o arquivo de copia de seguranza."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Insire un contrasinal para encriptar os datos da copia de seguranza completa. Se queda en branco este campo, usarase o contrasinal de copia de seguranza actual."</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se queres encriptar os datos da copia de seguranza completa, insire un contrasinal a continuación:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Como o teu dispositivo está cifrado, debes cifrar a túa copia de seguranza. Introduce un contrasinal a continuación:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os datos de restauración están encriptados, insire o contrasinal a continuación:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Iniciando copia de seguranza..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"A copia de seguranza rematou"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-hu/strings.xml b/packages/BackupRestoreConfirmation/res/values-hu/strings.xml
index b19b650..a402c56 100644
--- a/packages/BackupRestoreConfirmation/res/values-hu/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-hu/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Kérjük, adja meg az eszköz titkosítási jelszavát. Ezt használjuk a biztonsági mentések archívumának titkosításához is."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Kérjük, írjon be egy jelszót a teljes biztonsági mentés adatainak titkosításához. Ha üresen hagyja, jelenlegi biztonsági jelszavát fogjuk használni:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ha minden mentett adatot szeretne titkosítani, adjon meg egy jelszót alább:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Mivel az eszköz titkosítva van, a biztonsági mentést is titkosítani kell. Kérjük, alább adjon meg egy jelszót:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Ha a visszaállítási adatok titkosítva vannak, kérjük, adja meg a jelszót alább:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Biztonsági mentés indítása..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"A biztonsági mentés befejeződött"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-in/strings.xml b/packages/BackupRestoreConfirmation/res/values-in/strings.xml
index 305897b..f8d8d0a 100644
--- a/packages/BackupRestoreConfirmation/res/values-in/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-in/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Masukkan sandi enkripsi perangkat Anda di bawah. Sandi ini juga akan digunakan untuk mengenkripsi arsip cadangan."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Masukkan sandi yang digunakan untuk mengenkripsi data cadangan lengkap. Jika bidang ini dikosongkan, sandi cadangan Anda saat ini akan digunakan:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jika Anda ingin mengenkripsi data cadangan lengkap, masukkan sandi di bawah:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Karena perangkat Anda dienkripsi, Anda perlu mengenkripsi cadangan. Masukkan sandi di bawah:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Jika data pemulihan dienkripsi, masukkan sandi di bawah:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Pencadangan dimulai..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Pencadangan selesai"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-is-rIS/strings.xml b/packages/BackupRestoreConfirmation/res/values-is-rIS/strings.xml
index 768506b..13e5e52 100644
--- a/packages/BackupRestoreConfirmation/res/values-is-rIS/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-is-rIS/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Sláðu inn aðgangsorð fyrir dulkóðun tækis hér fyrir neðan. Það verður einnig notað til að dulkóða afritasafnið."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Sláðu inn aðgangsorð til að dulkóða gögn fullrar afritunar. Ef þetta er skilið eftir autt verður núverandi aðgangsorð fyrir afritun notað:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ef þú vilt dulkóða gögn fullrar afritunar skaltu slá inn aðgangsorð hér að neðan:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Þar sem tækið er dulkóðað þarftu að dulkóða öryggisafritið. Veldu aðgangsorð hér fyrir neðan:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Ef endurheimt gögn eru dulkóðuð skaltu slá inn aðgangsorðið hér að neðan:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Afritun er að hefjast..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Afritun lokið"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-it/strings.xml b/packages/BackupRestoreConfirmation/res/values-it/strings.xml
index c4b3a2d..2325d40 100644
--- a/packages/BackupRestoreConfirmation/res/values-it/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-it/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Inserisci la tua password di crittografia dispositivo di seguito. Verrà utilizzata anche per crittografare l\'archivio di backup."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Inserisci una password da utilizzare per la crittografia dei dati di backup completi. Se non ne inserisci una, verrà utilizzata la tua password di backup corrente:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se desideri crittografare tutti i dati di backup, inserisci una password qui di seguito:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Il dispositivo è crittografato, pertanto devi crittografare il backup. Inserisci una password di seguito:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Se i dati di ripristino sono crittografati, inserisci la password qui di seguito:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Avvio del backup..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Backup terminato"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-iw/strings.xml b/packages/BackupRestoreConfirmation/res/values-iw/strings.xml
index 74c0444..8c2ffaf 100644
--- a/packages/BackupRestoreConfirmation/res/values-iw/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-iw/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"הזן את סיסמת ההצפנה של המכשיר שלך בהמשך. הסיסמה תשמש גם להצפנת ארכיון הגיבוי."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"הזן סיסמה שתשמש להצפנה של נתוני הגיבוי המלא. אם תשאיר שדה זה ריק, ייעשה שימוש בסיסמת הגיבוי הנוכחית שלך:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"אם אתה רוצה להצפין את נתוני הגיבוי המלא, הזן סיסמה בהמשך:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"מכיוון שהמכשיר מוצפן, אתה נדרש להצפין את הגיבוי. הזן סיסמה בהמשך:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"אם נתוני השחזור מוצפנים, הזן את הסיסמה למטה:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"מתחיל בגיבוי..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"הגיבוי הסתיים"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-kn-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-kn-rIN/strings.xml
index db6f318..77ff317 100644
--- a/packages/BackupRestoreConfirmation/res/values-kn-rIN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-kn-rIN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"ದಯವಿಟ್ಟು ಕೆಳಗೆ ನಿಮ್ಮ ಸಾಧನದ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ. ಇದನ್ನು ಬ್ಯಾಕಪ್ ಆರ್ಕೈವ್ ಅನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಸಹ ಬಳಸಲಾಗುತ್ತದೆ."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"ಸಂಪೂರ್ಣ ಬ್ಯಾಕಪ್ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ. ಇದನ್ನು ಖಾಲಿಯಾಗಿಯೇ ಬಿಟ್ಟರೆ, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಬ್ಯಾಕಪ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"ನೀವು ಸಂಪೂರ್ಣ ಬ್ಯಾಕಪ್ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಬಯಸಿದರೆ, ಕಳಗೆ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿರುವ ಕಾರಣ, ನಿಮ್ಮ ಬ್ಯಾಕಪ್ ಅನ್ನು ನಿವು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ. ದಯವಿಟ್ಟು ಕೆಳಗೆ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"ಮರುಸ್ಥಾಪಿಸಲಾದ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದ್ದರೆ, ದಯವಿಟ್ಟು ಪಾಸ್‌ವರ್ಡ್ ಕೆಳಗೆ ನಮೂದಿಸಿ:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"ಬ್ಯಾಕಪ್ ಪ್ರಾರಂಭವಾಗುತ್ತಿದೆ..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"ಬ್ಯಾಕಪ್ ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-lo-rLA/strings.xml b/packages/BackupRestoreConfirmation/res/values-lo-rLA/strings.xml
index aacf050..ccac8ed 100644
--- a/packages/BackupRestoreConfirmation/res/values-lo-rLA/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-lo-rLA/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"ກະລຸນາປ້ອນລະຫັດຜ່ານການເຂົ້າລະຫັດອຸປະກອນຂອງທ່ານໃສ່ດ້ານລຸ່ມ. ລະຫັດນີ້ຍັງຈະໃຊ້ເພື່ອເຂົ້າລະຫັດຂໍ້ມູນທີ່ສຳຮອງໄວ້."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"ກະລຸນາປ້ອນລະຫັດຜ່ານ ເພື່ອໃຊ້ໃນການເຂົ້າລະຫັດການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບ. ຖ້າປ່ອຍໃຫ້ເປົ່າຫວ່າງໄວ້, ລະຫັດຜ່ານສຳຮອງຂໍ້ມູນທີ່ທ່ານໃຊ້ຢູ່ຈະຖືກນຳໃຊ້ແທນ:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"ຫາກທ່ານຕ້ອງການທີ່ຈະເຂົ້າລະຫັດໃຫ້ກັບການສຳຮອງຂໍ້ມູນທັງໝົດ, ກະລຸນາໃສ່ລະຫັດທາງລຸ່ມນີ້:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"ເນື່ອງ​ຈາກ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ຖືກ​ເຂົ້າ​ລະ​ຫັດ​ໄວ້, ທ່ານ​ຈຶ່ງ​ຕ້ອງ​ເຂົ້າ​ລະ​ຫັດ​ການ​ສຳ​ຮອງ​ຂໍ້​ມູນ​ຂອງ​ທ່ານ. ກະ​ລຸ​ນາ​ລະ​ບຸ​ລະ​ຫັດ​ຜ່ານ​ດ້ານ​ລຸ່ມ:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"ຫາກຂໍ້ມູນສຳຮອງຖືກເຂົ້າລະຫັດໄວ້, ກະລຸນາໃສ່ລະຫັດຜ່ານທາງດ້ານລຸ່ມນີ້:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"ກຳລັງເລີ່ມການສຳຮອງຂໍ້ມູນ..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"ສຳຮອງຂໍ້ມູນສຳເລັດແລ້ວ"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-lt/strings.xml b/packages/BackupRestoreConfirmation/res/values-lt/strings.xml
index 74bde67..093ff9d 100644
--- a/packages/BackupRestoreConfirmation/res/values-lt/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-lt/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Toliau įveskite įrenginio šifruotės slaptažodį. Jis bus naudojamas ir atsarginės kopijos archyvui šifruoti."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Įveskite slaptažodį, kuris bus naudojamas visai atsarginei duomenų kopijai šifruoti. Jei reikšmės neįvesite, bus naudojamas dabartinis atsarginės kopijos slaptažodis:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jei norite užšifruoti visą atsarginę duomenų kopiją, įveskite slaptažodį:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Kadangi jūsų įrenginys užšifruotas, turite užšifruoti atsarginę kopiją. Toliau įveskite slaptažodį:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Jei atkūrimo duomenys užšifruoti, įveskite toliau nurodytą slaptažodį:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Pradedama kurti atsarginę kopiją..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Atsarginė kopija sukurta"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-mk-rMK/strings.xml b/packages/BackupRestoreConfirmation/res/values-mk-rMK/strings.xml
index b07d721..3e295c1 100644
--- a/packages/BackupRestoreConfirmation/res/values-mk-rMK/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-mk-rMK/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Внесете ја лозинката за шифрирање на вашиот уред подолу. Таа ќе се користи и за шифрирање на резервната копија на архивата."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Внесете лозинка што ќе се користи за шифрирање на целосната резервна копија на податоците. Ако ова поле остане празно, ќе се користи вашата тековна лозинка за резервна копија:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ако сакате да ја шифрирате целосната резервна копија на податоци, внесете лозинка подолу:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Бидејќи уредот е шифриран, треба да ја шифрирате и резервната копија. Внесете лозинка подолу:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Ако податоците што се враќаат се шифрирани, внесете ја лозинката подолу:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Започнува правење резервна копија..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Правењето резервна копија заврши"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-ml-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-ml-rIN/strings.xml
index 2c1d953..b2b4bcb 100644
--- a/packages/BackupRestoreConfirmation/res/values-ml-rIN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ml-rIN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"നിങ്ങളുടെ ഉപകരണ എൻക്രിപ്‌ഷൻ പാസ്‌വേഡ് ചുവടെ നൽകുക. ബാക്കപ്പ് ആർക്കൈവ് എൻക്രിപ്റ്റുചെയ്യാനും ഇത് ഉപയോഗിക്കുന്നു."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"പൂർണ്ണ ബാക്കപ്പ് ഡാറ്റ എൻക്രിപ്‌റ്റ് ചെയ്യുന്നതിനായി ഉപയോഗിക്കാൻ ഒരു പാസ്‌വേഡ് നൽകുക. ഇത് ശൂന്യമായി വിടുകയാണെങ്കിൽ, നിങ്ങളുടെ നിലവിലെ ബാക്കപ്പ് പാസ്‌വേഡ് ഉപയോഗിക്കും:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"പൂർണ്ണ ബാക്കപ്പ് ഡാറ്റ എൻക്രിപ്‌റ്റ് ചെയ്യണമെങ്കിൽ, ചുവടെ ഒരു പാസ്‌വേഡ് നൽകുക:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"നിങ്ങളുടെ ഉപകരണം എൻക്രിപ്റ്റുചെയ്‌തതിനാൽ, ബാക്കപ്പ് എൻക്രിപ്റ്റുചെയ്യേണ്ടതുണ്ട്. ചുവടെ പാസ്‌വേഡ് നൽകുക:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"പുനഃസ്ഥാപിച്ച ഡാറ്റ എൻക്രിപ്‌റ്റ് ചെയ്‌തിട്ടുണ്ടെങ്കിൽ, പാസ്‌വേഡ് ചുവടെ നൽകുക:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"ബാക്കപ്പ് ആരംഭിക്കുന്നു..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"ബാക്കപ്പ് പൂർത്തിയായി"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-mn-rMN/strings.xml b/packages/BackupRestoreConfirmation/res/values-mn-rMN/strings.xml
index 32d60b7..dc8aa17 100644
--- a/packages/BackupRestoreConfirmation/res/values-mn-rMN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-mn-rMN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Төхөөрөмж шифрлэх нууц үгийг доор оруулна уу. Энэ нууц үгийг нөөшлөх архивийг шифрлэхэд бас ашиглана."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Бүрэн дата нөөшлөлтийг шифрлэхэд ашиглах нууц үгийг оруулна уу. Хэрэв та хоосон үлдээвэл таны одоогийн нөөшлөлтийн нууц үг ашиглагдах болно:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Хэрэв та бүрэн нөөшлөх датаг шифрлэх бол доор нууц үгийг оруулна уу:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Таны төхөөрөмж шифрлэгдсэн тул та нөөшлөлтийг мөн шифрлэх шаардлагатай. Нууц үгийг доор оруулна уу:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Хэрэв сэргээх дата шифрлэгдсэн бол доор нууц үгийг оруулна уу:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Нөөшлөж эхлэх..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Нөөшлөлт дуусав"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-mr-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-mr-rIN/strings.xml
index 882fa1a..121ad00 100644
--- a/packages/BackupRestoreConfirmation/res/values-mr-rIN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-mr-rIN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया आपला डिव्‍हाइस कूटबद्धीकरण संकेतशब्‍द खाली प्रविष्‍‍ट करा. हा बॅकअप संग्रह कूटबद्ध करण्‍यासाठी देखील वापरला जाईल."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया पूर्ण बॅकअप डेटा कूटबद्ध करण्‍यासाठी वापरण्याकरिता संकेतशब्‍द प्रविष्‍ट करा. हे रिक्त सोडल्‍यास, आपला वर्तमान बॅकअप संकेतशब्‍द वापरला जाईल:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"आपण पूर्ण बॅकअप डेटा कूटबद्ध करू इच्‍छित असल्‍यास, खालील संकेतशब्‍द प्रविष्‍ट करा:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"आपले डिव्हाइस कूटबद्ध केले असल्यामुळे, आपल्याला आपला बॅक अप कूटबद्ध करणे आवश्यक आहे. कृपया खाली एक संकेतशब्द प्रविष्ट करा:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"पुनर्संचयित डेटा कूटबद्ध केला असल्‍यास, कृपया संकेतशब्‍द खाली प्रविष्‍ट करा:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"बॅकअप सुरू होत आहे..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"बॅकअप समाप्त झाले"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml b/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml
index e514c29..d499771 100644
--- a/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"သင့်စက်၏လျှို့ဝှက်အသွင်ပြောင်းခြင်းအတွက် လျှို့ဝှက်စကားဝှက်အားထည့်ပါ။ အရံသိမ်းဆည်းမှု သိမ်းဆည်းနေရာတွင်လည်း အသုံးပြုမည်ဖြစ်သည်။"</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"ဒေတာအားလုံးအားအရန်သိမ်းဆည်းခြင်းပြီးလျှို့ဝှက်အသွင်ပြောင်းခြင်းအတွက် လျှို့ဝှက်နံပါတ်/စာကိုထည့်ပါ။ အကယ်၍ ကွက်လပ်ထားပါက ယခုသင့်လက်ရှိလျှို့ဝှက်စကားဝှက်အား အသုံးပြုပါမည်။"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"အကယ်၍ ဒေတာအားလုံးအားအရန်သိမ်းဆည်းခြင်းကို ဝှက်လိုပါက အောက်တွင်လျှို့ဝှက်နံပါတ်/စာကိုထည့်ပါ။"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"သင်၏ ကိရိယာကို လျှို့ဝျက်ကုဒ် သွင်းထားရာ၊ သင်သည် သင်၏ ဘက်အာပ်ကိုပါ  လျှို့ဝျက်ကုဒ် သွင်းရန် လိုအပ်သည်။ ကျေးဇူးပြုပြီး အောက်မှာ စကားဝှက်ကို ထည့်သွင်းပါ:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"အကယ်၍ ပြန်လည်ရယူမည့်ဒေတာမှာလျှို့ဝှက်အသွင်ပြောင်းထားပါက အောက်တွင်စကားဝှက်ကိုထည့်ပါ-"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Backupစတင်ပြုလုပ်နေသည်"</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Backupလုပ်ခြင်းပြီးဆုံးပါပြီ"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-nb/strings.xml b/packages/BackupRestoreConfirmation/res/values-nb/strings.xml
index 9c996ed..8d5bc19 100644
--- a/packages/BackupRestoreConfirmation/res/values-nb/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-nb/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Skriv inn krypteringspassordet for enheten din nedenfor. Dette brukes også til å kryptere arkivet for sikkerhetskopier."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Skriv inn et passord for kryptering av full sikkerhetskopi. Hvis feltet er tomt, brukes det gjeldende passordet ditt for sikkerhetskopiering:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Hvis du vil kryptere alle de sikkerhetskopierte dataene, skriver du inn et passord nedenfor:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Siden enheten din er kryptert, er du nødt til å kryptere sikkerhetskopien din. Angi et passord nedenfor:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Hvis de gjenopprettede dataene er krypterte, må du skrive inn passordet nedenfor:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Sikkerhetskopiering er i gang …"</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Sikkerhetskopieringen er fullført"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-nl/strings.xml b/packages/BackupRestoreConfirmation/res/values-nl/strings.xml
index 07054cc..f483b14 100644
--- a/packages/BackupRestoreConfirmation/res/values-nl/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-nl/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Geef hieronder uw wachtwoord voor apparaatversleuteling op. Dit wordt ook gebruikt om het back-uparchief te versleutelen."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Geef een wachtwoord op dat u wilt gebruiken voor het coderen van de gegevens van de volledige back-up. Als u dit leeg laat, wordt uw huidige back-upwachtwoord gebruikt:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Als u de gegevens van de volledige back-up wilt versleutelen, geeft u daarvoor hieronder een wachtwoord op:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Aangezien uw apparaat is gecodeerd, moet u uw back-up coderen. Geef hieronder een wachtwoord op:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Als deze herstelgegevens zijn gecodeerd, geeft u hieronder het wachtwoord op:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Back-up starten..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Back-up voltooid"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pl/strings.xml b/packages/BackupRestoreConfirmation/res/values-pl/strings.xml
index e2219d2..81908b3 100644
--- a/packages/BackupRestoreConfirmation/res/values-pl/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pl/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Wpisz poniżej hasło szyfrowania urządzenia. Służy ono również do szyfrowania archiwum kopii zapasowych."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Wpisz hasło do zaszyfrowania pełnej kopii zapasowej. Jeśli pozostawisz puste pole, zostanie użyte aktualne hasło kopii zapasowej:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jeśli chcesz zaszyfrować pełną kopię zapasową, wprowadź poniżej hasło:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Ponieważ Twoje urządzenie jest szyfrowane, musisz też zaszyfrować jego kopię zapasową. Wpisz hasło poniżej:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Jeśli przywracane dane są zaszyfrowane, wpisz poniżej hasło:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Tworzenie kopii zapasowej..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Utworzono kopię zapasową"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
index 83aa06d..ecaa069 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduza a palavra-passe de encriptação do dispositivo abaixo. Esta também será utilizada para encriptar o arquivo da cópia de segurança."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduza uma palavra-passe a utilizar para encriptar os dados da cópia de segurança completa. Se deixar o campo em branco, será utilizada a palavra-passe de cópia de segurança atual."</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se pretender encriptar os dados da cópia de segurança completa, introduza uma palavra-passe abaixo:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Uma vez que o seu dispositivo está encriptado, tem de encriptar a sua cópia de segurança. Introduza uma palavra-passe abaixo:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados a restaurar estiverem encriptados, introduza a palavra-passe abaixo:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"A iniciar cópia de segurança..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Cópia de segurança concluída"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-sv/strings.xml b/packages/BackupRestoreConfirmation/res/values-sv/strings.xml
index 6bbbbfb5..3ae37cf 100644
--- a/packages/BackupRestoreConfirmation/res/values-sv/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-sv/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Ange lösenordet för enhetskryptering nedan. Lösenordet kommer även att användas för att kryptera säkerhetskopian."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Ange ett lösenord för kryptering av alla säkerhetskopierade data. Om det här lämnas tomt kommer ditt nuvarande lösenord för säkerhetskopior att användas:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Om du vill kryptera alla säkerhetskopierade data anger du ett lösenord nedan:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Eftersom enheten är krypterad måste du kryptera säkerhetskopierade data. Ange lösenordet nedan:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Om återställda data är krypterade anger du lösenordet nedan:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Säkerhetskopieringen har startat ..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Säkerhetskopieringen har slutförts"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-sw/strings.xml b/packages/BackupRestoreConfirmation/res/values-sw/strings.xml
index 1f5175f..530efc0 100644
--- a/packages/BackupRestoreConfirmation/res/values-sw/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-sw/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Tafadhali weka nenosiri lako la kusimba kifaa kwa njia fiche hapo chini. Pia litatumika kusimba kumbukumbu za nakala kwa njia fiche."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Tafadhali weka nenosiri la kutumia katika kusimba nakala kamili za data kwa njia fiche. Ikiwa sehemu hii itawachwa wazi, nenosiri lako la sasa litatumika:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ikiwa unataka kusimba nakala za data kwa njia fiche, weka nenosiri hapo chini:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Kwa kuwa kifaa chako kimesimbwa kwa njia fiche, unatakiwa usimbe hifadhi rudufu yako kwa njia fiche. Tafadhali weka nenosiri hapo chini:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Ikiwa data imesimbwa kwa njia fiche, tafadhali weka nenosiri lake hapo chini:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Inaanza kuhifadhi..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Imemaliza kuhifadhi"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-ta-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-ta-rIN/strings.xml
index ee9605a..0a7ffae 100644
--- a/packages/BackupRestoreConfirmation/res/values-ta-rIN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ta-rIN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"உங்கள் சாதன முறைமையாக்கல் கடவுச்சொல்லைக் கீழே உள்ளிடவும். இது காப்புப் பிரதி இயக்ககத்தை முறைமையாக்கவும் பயன்படுத்தப்படும்."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"காப்புப் பிரதி எடுக்கப்பட்ட முழு தரவையும் முறைமையாக்க கடவுச்சொல்லை உள்ளிடவும். இதைக் காலியாக விட்டால், உங்கள் தற்போதைய காப்புப் பிரதி கடவுச்சொல் பயன்படுத்தப்படும்:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"காப்புப் பிரதி எடுக்கப்பட்ட முழு தரவையும் முறைமையாக்க விரும்பினால், கடவுச்சொல்லை உள்ளிடவும்:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"சாதனம் மறையாக்கப்பட்டுள்ளதால், காப்புப்பிரதியையும் மறையாக்க வேண்டும். கீழே கடவுச்சொல்லை உள்ளிடவும்:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"மீட்டமைக்கப்பட்ட தரவு முறைமையாக்கப்பட்டிருந்தால், கீழே கடவுச்சொல்லை உள்ளிடவும்:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"காப்புப் பிரதி எடுக்க தொடங்குகிறது..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"காப்புப் பிரதி எடுப்பது முடிந்தது"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-te-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-te-rIN/strings.xml
index abc6a16..52916d8 100644
--- a/packages/BackupRestoreConfirmation/res/values-te-rIN/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-te-rIN/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"దయచేసి దిగువ మీ పరికర గుప్తీకరణ పాస్‌వర్డ్‌ను నమోదు చేయండి. ఇది బ్యాకప్ ఆర్కైవ్‌ను గుప్తీకరించడానికి కూడా ఉపయోగించబడుతుంది."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"దయచేసి పూర్తి బ్యాకప్ డేటాను గుప్తీకరించడం కోసం ఉపయోగించడానికి పాస్‌వర్డ్‌ను నమోదు చేయండి. దీన్ని ఖాళీగా వదిలిపెడితే, మీ ప్రస్తుత బ్యాకప్ పాస్‌వర్డ్ ఉపయోగించబడుతుంది:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"మీరు పూర్తి బ్యాకప్ డేటాను గుప్తీకరించాలని కోరుకుంటున్నట్లయితే, దిగువ పాస్‌వర్డ్‌ను నమోదు చేయండి:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"మీ పరికరం గుప్తీకరించబడినందున, మీరు మీ బ్యాకప్‌ని గుప్తీకరించాల్సి ఉంటుంది. దయచేసి దిగువ పాస్‌వర్డ్‌ని నమోదు చేయండి:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"పునరుద్ధరణ డేటా గుప్తీకరించబడుంటే, దయచేసి దిగువ పాస్‌వర్డ్‌ను నమోదు చేయండి:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"బ్యాకప్ ప్రారంభమవుతోంది..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"బ్యాకప్ పూర్తయింది"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-uk/strings.xml b/packages/BackupRestoreConfirmation/res/values-uk/strings.xml
index 476629e..f3d529e 100644
--- a/packages/BackupRestoreConfirmation/res/values-uk/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-uk/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Нижче введіть свій пароль шифрування пристрою. Він також використовуватиметься для шифрування архіву резервної копії."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Введіть пароль, який використовується для шифрування повного резервного копіювання даних. Якщо залишити це поле порожнім, буде використано поточний пароль резервного копіювання."</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Якщо ви хочете зашифрувати повне резервне копіювання даних, введіть пароль нижче:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Оскільки ваш пристрій зашифровано, потрібно також зашифрувати резервну копію даних. Введіть пароль нижче."</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Якщо дані для відновлення зашифровано, введіть пароль нижче:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Початок резервного копіювання..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Резервне копіювання закінчено"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-zu/strings.xml b/packages/BackupRestoreConfirmation/res/values-zu/strings.xml
index 57fdcc3f..90259e1 100644
--- a/packages/BackupRestoreConfirmation/res/values-zu/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-zu/strings.xml
@@ -29,8 +29,7 @@
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Uyacelwa ukuba ufake iphasiwedi efakwe kudivayisi yakho ngezansi. lokhu kuzosetshenziswa ukufaka kusilondoloza sokusiza lapho kudingeka."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Sicela ufake iphasiwedi ezosetshenziselwa ukubhala ngokufihlekileyo imininingo eyesekwe ngokulondoloza. Uma lokhu kushiywe kungabhalwe lutho, kuzosetshenziswa iphasiwedi yokweseka ngokulondoloza yamanje:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Uma ufuna ukufaka ikhowudi kwimininingo yonke eyesekelwe ngokulondoloza faka i-passowrd engezansi:"</string>
-    <!-- no translation found for backup_enc_password_required (7889652203371654149) -->
-    <skip />
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"Njengoba idivayisi yakho ibethelwe, kudingeka ukuthi ubethele isipele sakho. Sicela ufake iphasiwedi ngezansi:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Uma uhlelo lokusebenza yokubuyiselwa esimweni kwmininingo ibhalwe ngokufihlekileyo, sicela ufake iphasiwedi engezansi:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Ukulondoloza kuyaqala..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Ukulondoloza kuphelile"</string>
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index ee5d42a..761d58a 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -27,6 +27,7 @@
         android:id="@+id/static_content"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
+        android:paddingStart="8dip"
         android:elevation="@dimen/preview_controls_elevation"
         android:background="?android:attr/colorPrimary">
 
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index 0629481..c2a0da9 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -55,8 +55,7 @@
                     android:text="@string/label_copies">
                 </TextView>
 
-                <view
-                    class="com.android.printspooler.widget.FirstFocusableEditText"
+                <EditText
                     android:id="@+id/copies_edittext"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
@@ -64,7 +63,7 @@
                     android:singleLine="true"
                     android:ellipsize="end"
                     android:inputType="numberDecimal">
-                </view>
+                </EditText>
 
             </LinearLayout>
 
@@ -198,8 +197,7 @@
                     android:visibility="visible">
                 </TextView>
 
-                <view
-                    class="com.android.printspooler.widget.FirstFocusableEditText"
+                <EditText
                     android:id="@+id/page_range_edittext"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
@@ -208,7 +206,7 @@
                     android:ellipsize="end"
                     android:visibility="visible"
                     android:inputType="textNoSuggestions">
-                </view>
+                </EditText>
 
             </LinearLayout>
 
diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
index 43d8aaf..4381a7a 100644
--- a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
@@ -17,8 +17,8 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
-      android:paddingStart="16dip"
-      android:paddingEnd="16dip"
+      android:paddingStart="8dip"
+      android:paddingEnd="8dip"
       android:minHeight="56dip"
       android:orientation="horizontal"
       android:gravity="start|center_vertical">
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index 173057b..77c500a 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -23,8 +23,6 @@
         android:id="@android:id/list"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
-        android:paddingStart="@dimen/printer_list_view_padding_start"
-        android:paddingEnd="@dimen/printer_list_view_padding_end"
         android:scrollbarStyle="outsideOverlay"
         android:cacheColorHint="@android:color/transparent"
         android:scrollbarAlwaysDrawVerticalTrack="true" >
diff --git a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
deleted file mode 100644
index 14403a1..0000000
--- a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
-    android:orientation="vertical"
-    android:gravity="start|center_vertical">
-
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="?android:attr/spinnerDropDownItemStyle"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="?android:attr/textColorPrimary"
-        android:singleLine="true"
-        android:ellipsize="end"
-        android:textIsSelectable="false"
-        android:gravity="top|left"
-        android:duplicateParentState="true">
-    </TextView>
-
-    <TextView
-        android:id="@+id/subtitle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="?android:attr/spinnerDropDownItemStyle"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorPrimary"
-        android:singleLine="true"
-        android:ellipsize="end"
-        android:textIsSelectable="false"
-        android:visibility="gone"
-        android:duplicateParentState="true">
-    </TextView>
-
-</LinearLayout>
diff --git a/packages/PrintSpooler/res/values-land/constants.xml b/packages/PrintSpooler/res/values-land/constants.xml
index a4666a5..6cf9754b5 100644
--- a/packages/PrintSpooler/res/values-land/constants.xml
+++ b/packages/PrintSpooler/res/values-land/constants.xml
@@ -16,10 +16,6 @@
 
 <resources>
 
-    <dimen name="printer_list_view_padding_start">48dip</dimen>
-
-    <dimen name="printer_list_view_padding_end">48dip</dimen>
-
     <integer name="preview_page_per_row_count">2</integer>
 
     <integer name="print_option_column_count">3</integer>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index b95703b..b4e4777 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -28,9 +28,6 @@
 
     <dimen name="print_dialog_frame_max_width_dip">400dip</dimen>
 
-    <dimen name="printer_list_view_padding_start">16dip</dimen>
-    <dimen name="printer_list_view_padding_end">16dip</dimen>
-
     <dimen name="selected_page_elevation">6dip</dimen>
     <dimen name="unselected_page_elevation">2dip</dimen>
 
@@ -46,6 +43,6 @@
     <fraction name="page_unselected_alpha">50%</fraction>
 
     <dimen name="preview_page_footer_height">32dip</dimen>
-    <dimen name="preview_page_min_width">130dip</dimen>
+    <dimen name="preview_page_min_width">128dip</dimen>
 
 </resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index db319e9..532b01f 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,7 +16,10 @@
 
 <resources>
 
-    <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
+    <style name="PrintActivity" parent="@android:style/Theme.Material">
+        <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
+        <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
+        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 5bcdb9f..d949673 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -289,15 +289,11 @@
                     + " for position: " + position);
         }
 
-        final int pageCount = getItemCount();
         MyViewHolder myHolder = (MyViewHolder) holder;
 
         View page = holder.itemView;
-        if (pageCount > 1) {
-            page.setOnClickListener(mPageClickListener);
-        } else {
-            page.setOnClickListener(null);
-        }
+        page.setOnClickListener(mPageClickListener);
+
         page.setTag(holder);
 
         myHolder.mPageInAdapter = position;
@@ -339,16 +335,9 @@
         }
         content.init(provider, mMediaSize, mMinMargins);
 
-
         View pageSelector = page.findViewById(R.id.page_selector);
         pageSelector.setTag(myHolder);
-        if (pageCount > 1) {
-            pageSelector.setOnClickListener(mPageClickListener);
-            pageSelector.setVisibility(View.VISIBLE);
-        } else {
-            pageSelector.setOnClickListener(null);
-            pageSelector.setVisibility(View.GONE);
-        }
+        pageSelector.setOnClickListener(mPageClickListener);
 
         if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) {
             pageSelector.setSelected(true);
@@ -449,8 +438,9 @@
 
         final int verticalPadding;
         if (mPageContentHeight + mFooterHeight + mPreviewListPadding > availableHeight) {
-            verticalPadding = Math.max(mPreviewPageMargin,
-                    (availableHeight - totalContentHeight) / 2);
+            verticalPadding = Math.max(0,
+                    (availableHeight - mPageContentHeight - mFooterHeight) / 2
+                            - mPreviewPageMargin);
         } else {
             verticalPadding = Math.max(mPreviewListPadding,
                     (availableHeight - totalContentHeight) / 2);
@@ -791,6 +781,9 @@
                 page.animate().translationZ(mSelectedPageElevation)
                         .alpha(mSelectedPageAlpha);
             } else {
+                if (mConfirmedPagesInDocument.size() <= 1) {
+                    return;
+                }
                 mConfirmedPagesInDocument.remove(pageInDocument);
                 pageSelector.setSelected(false);
                 page.animate().translationZ(mUnselectedPageElevation)
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index fe17516..01c9746 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -982,21 +982,21 @@
 
         // Media size.
         mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
-                this, R.layout.spinner_dropdown_item, R.id.title);
+                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
         mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
         mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
         mMediaSizeSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Color mode.
         mColorModeSpinnerAdapter = new ArrayAdapter<>(
-                this, R.layout.spinner_dropdown_item, R.id.title);
+                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
         mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
         mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
         mColorModeSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Orientation
         mOrientationSpinnerAdapter = new ArrayAdapter<>(
-                this, R.layout.spinner_dropdown_item, R.id.title);
+                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
         String[] orientationLabels = getResources().getStringArray(
                 R.array.orientation_labels);
         mOrientationSpinnerAdapter.add(new SpinnerItem<>(
@@ -1008,8 +1008,8 @@
         mOrientationSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Range options
-        ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
-                new ArrayAdapter<>(this, R.layout.spinner_dropdown_item, R.id.title);
+        ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter = new ArrayAdapter<>(
+                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
         mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
         mRangeOptionsSpinner.setAdapter(rangeOptionsSpinnerAdapter);
         mRangeOptionsSpinner.setOnItemSelectedListener(itemSelectedListener);
@@ -1075,6 +1075,7 @@
                 mDestinationSpinner.setEnabled(false);
             }
             mCopiesEditText.setEnabled(false);
+            mCopiesEditText.setFocusable(false);
             mMediaSizeSpinner.setEnabled(false);
             mColorModeSpinner.setEnabled(false);
             mOrientationSpinner.setEnabled(false);
@@ -1089,6 +1090,7 @@
         // available, we disable all print options except the destination.
         if (mCurrentPrinter == null || !canPrint(mCurrentPrinter)) {
             mCopiesEditText.setEnabled(false);
+            mCopiesEditText.setFocusable(false);
             mMediaSizeSpinner.setEnabled(false);
             mColorModeSpinner.setEnabled(false);
             mOrientationSpinner.setEnabled(false);
@@ -1316,8 +1318,10 @@
         // Copies
         if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
             mCopiesEditText.setEnabled(true);
+            mCopiesEditText.setFocusableInTouchMode(true);
         } else {
             mCopiesEditText.setEnabled(false);
+            mCopiesEditText.setFocusable(false);
         }
         if (mCopiesEditText.getError() == null
                 && TextUtils.isEmpty(mCopiesEditText.getText())) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/FirstFocusableEditText.java b/packages/PrintSpooler/src/com/android/printspooler/widget/FirstFocusableEditText.java
deleted file mode 100644
index d6bb7c8..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/FirstFocusableEditText.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler.widget;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.widget.EditText;
-
-/**
- * An instance of this class class is intended to be the first focusable
- * in a layout to which the system automatically gives focus. It performs
- * some voodoo to avoid the first tap on it to start an edit mode, rather
- * to bring up the IME, i.e. to get the behavior as if the view was not
- * focused.
- */
-public final class FirstFocusableEditText extends EditText {
-    private boolean mClickedBeforeFocus;
-    private CharSequence mError;
-
-    public FirstFocusableEditText(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    public boolean performClick() {
-        super.performClick();
-        if (isFocused() && !mClickedBeforeFocus) {
-            clearFocus();
-            requestFocus();
-        }
-        mClickedBeforeFocus = true;
-        return true;
-    }
-
-    @Override
-    public CharSequence getError() {
-        return mError;
-    }
-
-    @Override
-    public void setError(CharSequence error, Drawable icon) {
-        setCompoundDrawables(null, null, icon, null);
-        mError = error;
-    }
-
-    protected void onFocusChanged(boolean gainFocus, int direction,
-            Rect previouslyFocusedRect) {
-        if (!gainFocus) {
-            mClickedBeforeFocus = false;
-        }
-        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
-    }
-}
\ No newline at end of file
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index e428948..c84b06a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -152,6 +152,17 @@
 
         // Make sure we start in a closed options state.
         onDragProgress(1.0f);
+
+        // The framework gives focus to the frist focusable and we
+        // do not want that, hence we will take focus instead.
+        setFocusableInTouchMode(true);
+    }
+
+    @Override
+    public void focusableViewAvailable(View v) {
+        // The framework gives focus to the frist focusable and we
+        // do not want that, hence do not announce new focusables.
+        return;
     }
 
     @Override
@@ -309,6 +320,7 @@
             mSummaryContent.setLayerType(View.LAYER_TYPE_NONE, null);
             mDraggableContent.setLayerType(View.LAYER_TYPE_NONE, null);
             mMoreOptionsButton.setLayerType(View.LAYER_TYPE_NONE, null);
+            mMoreOptionsButton.setLayerType(View.LAYER_TYPE_NONE, null);
         }
 
         mDragProgress = progress;
@@ -320,7 +332,6 @@
         mMoreOptionsButton.setAlpha(inverseAlpha);
 
         mEmbeddedContentScrim.setBackgroundColor(computeScrimColor());
-
         if (progress == 0) {
             if (mOptionsStateChangeListener != null) {
                 mOptionsStateChangeListener.onOptionsOpened();
@@ -354,14 +365,15 @@
     }
 
     private void ensureImeClosedAndInputFocusCleared() {
-        View focus = findFocus();
-        if (focus != null) {
+        View focused = findFocus();
+
+        if (focused != null && focused.isFocused()) {
             InputMethodManager imm = (InputMethodManager) mContext.getSystemService(
                     Context.INPUT_METHOD_SERVICE);
-            if (imm.isActive(focus)) {
+            if (imm.isActive(focused)) {
                 imm.hideSoftInputFromWindow(getWindowToken(), 0);
             }
-            focus.clearFocus();
+            focused.clearFocus();
         }
     }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 87c015c..4ef2189 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -318,10 +318,10 @@
         }
     }
 
-    private void checkUserRestrictions(String setting) {
+    private void checkUserRestrictions(String setting, int userId) {
         String userRestriction = sRestrictedKeys.get(setting);
         if (!TextUtils.isEmpty(userRestriction)
-            && mUserManager.hasUserRestriction(userRestriction)) {
+            && mUserManager.hasUserRestriction(userRestriction, new UserHandle(userId))) {
             throw new SecurityException(
                     "Permission denial: user is restricted from changing this setting.");
         }
@@ -936,7 +936,7 @@
         try {
             int numValues = values.length;
             for (int i = 0; i < numValues; i++) {
-                checkUserRestrictions(values[i].getAsString(Settings.Secure.NAME));
+                checkUserRestrictions(values[i].getAsString(Settings.Secure.NAME), callingUser);
                 if (db.insert(args.table, null, values[i]) < 0) return 0;
                 SettingsCache.populate(cache, values[i]);
                 if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + values[i]);
@@ -1067,7 +1067,7 @@
         // Check write permissions only after determining which table the insert will touch
         checkWritePermissions(args);
 
-        checkUserRestrictions(name);
+        checkUserRestrictions(name, desiredUserHandle);
 
         // The global table is stored under the owner, always
         if (TABLE_GLOBAL.equals(args.table)) {
@@ -1143,7 +1143,7 @@
             callingUser = UserHandle.USER_OWNER;
         }
         checkWritePermissions(args);
-        checkUserRestrictions(initialValues.getAsString(Settings.Secure.NAME));
+        checkUserRestrictions(initialValues.getAsString(Settings.Secure.NAME), callingUser);
 
         final AtomicInteger mutationCount = sKnownMutationsInFlight.get(callingUser);
         mutationCount.incrementAndGet();
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png
deleted file mode 100644
index f256fbb..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png
deleted file mode 100644
index b946ec9..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png
deleted file mode 100644
index b1e984c..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png
deleted file mode 100644
index ceda1bb..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png
deleted file mode 100644
index 47be502..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png
deleted file mode 100644
index 4b12809..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png
deleted file mode 100644
index 8e225af..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png
deleted file mode 100644
index 937202b..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/stat_sys_cast.xml b/packages/SystemUI/res/drawable/stat_sys_cast.xml
new file mode 100644
index 0000000..c9e65e0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_cast.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="18dp"
+        android:height="18dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/data_usage.xml b/packages/SystemUI/res/layout/data_usage.xml
index 8831a05..c943f3d 100644
--- a/packages/SystemUI/res/layout/data_usage.xml
+++ b/packages/SystemUI/res/layout/data_usage.xml
@@ -14,7 +14,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.systemui.qs.tiles.DataUsageDetailView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingTop="16dp"
@@ -82,4 +82,4 @@
             android:textAppearance="@style/TextAppearance.QS.DataUsage.Secondary" />
     </LinearLayout>
 
-</LinearLayout>
\ No newline at end of file
+</com.android.systemui.qs.tiles.DataUsageDetailView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index ef0c9bb..ca07c87 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -67,6 +67,6 @@
         android:src="@drawable/ic_lock_24dp"
         android:scaleType="center"
         android:tint="#ffffffff"
-        android:contentDescription="@string/accessibility_unlock_button_not_secured" />
+        android:contentDescription="@string/accessibility_unlock_button" />
 
 </com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index d65a23e..566c304 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -53,7 +53,7 @@
                     android:layout_height="wrap_content"
                     android:layout_gravity="center_vertical|start"
                     android:layout_weight="1"
-                    android:textAppearance="@*android:style/TextAppearance.StatusBar.Material.EventContent.Title"
+                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
                     android:textColor="@color/notification_guts_title_color"
                     />
             <DateTimeView
@@ -62,7 +62,7 @@
                     android:layout_height="wrap_content"
                     android:layout_weight="0"
                     android:layout_gravity="center_vertical|start"
-                    android:textAppearance="@*android:style/TextAppearance.StatusBar.Material.EventContent.Time"
+                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Time"
                     android:textColor="@color/notification_guts_text_color"
                     />
             <TextView
@@ -70,7 +70,7 @@
                     android:layout_height="wrap_content"
                     android:id="@+id/debug_info"
                     android:layout_weight="0"
-                    android:textAppearance="@*android:style/TextAppearance.StatusBar.Material.EventContent.Time"
+                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Time"
                     android:layout_gravity="bottom|start"
                     android:visibility="gone"
                     android:textColor="@color/notification_guts_text_color"
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 2322f16..af22f03 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -44,7 +44,7 @@
             android:id="@+id/user_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textSize="14sp"
+            android:textSize="@dimen/qs_detail_item_secondary_text_size"
             android:textColor="@color/qs_user_detail_name"
             android:gravity="center_horizontal" />
 
diff --git a/packages/SystemUI/res/layout/split_clock_view.xml b/packages/SystemUI/res/layout/split_clock_view.xml
index 87b7051..808460a 100644
--- a/packages/SystemUI/res/layout/split_clock_view.xml
+++ b/packages/SystemUI/res/layout/split_clock_view.xml
@@ -39,6 +39,7 @@
 
     <!-- Empty text view so we have the same height when expanded/collapsed-->
     <TextView
+        android:id="@+id/empty_time_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:visibility="invisible"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index ef8a426..f9e7852 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -87,6 +87,7 @@
         android:visibility="gone"
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
         android:text="@*android:string/emergency_calls_only"
+        android:singleLine="true"
         android:gravity="center_vertical" />
 
     <FrameLayout
diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
index 902b837..9e0f82cb 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
@@ -27,5 +27,6 @@
             android:layout_height="48dp"
             android:layout_gravity="end"
             android:src="@drawable/ic_dismiss_all"
-            android:background="@drawable/ripple_drawable" />
+            android:background="@drawable/ripple_drawable"
+            android:contentDescription="@string/accessibility_clear_all" />
 </com.android.systemui.statusbar.DismissView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index eff3758..351177b 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -38,8 +38,8 @@
             android:id="@+id/more_text"
             android:layout_width="32dp"
             android:layout_height="32dp"
-            android:layout_marginStart="20dp"
-            android:layout_marginEnd="16dp"
+            android:layout_marginStart="16dp"
+            android:layout_marginEnd="12dp"
             android:layout_gravity="center_vertical"
             android:background="@drawable/keyguard_overflow_number_background"
             android:gravity="center"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 3949d7d..14bf10e 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -88,14 +88,4 @@
         android:orientation="vertical"
         android:paddingBottom="@dimen/qs_panel_padding" />
 
-    <TextView
-        android:id="@+id/zen_alarm_warning"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/qs_panel_padding"
-        android:paddingLeft="@dimen/qs_panel_padding"
-        android:paddingRight="@dimen/qs_panel_padding"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp"
-        android:textAppearance="@style/TextAppearance.QS.Subhead" />
 </com.android.systemui.volume.ZenModePanel>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7873cbd..e2b4475 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ontsluit"</string>
     <string name="phone_label" msgid="2320074140205331708">"maak foon oop"</string>
     <string name="camera_label" msgid="7261107956054836961">"maak kamera oop"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Toestel beveilig."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Toestel nie beveilig nie."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Toestel beveilig, vertrouensagent aktief."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Toestel nie beveilig nie, vertrouensagent aktief."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Gesigherkenning werk tans, vertrouensagent aktief."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knoppie vir wissel van invoermetode."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Versoenbaarheid-zoem se knoppie."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoem kleiner na groter skerm."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Hierdie toestel word bestuur deur:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJou administrateur kan jou netwerkaktiwiteit monitor, insluitend e-posse, programme en veilige webwerwe. Kontak jou administrateur vir meer inligting.\n\nJy het ook \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" toestemming gegee om \'n VPN-verbinding op te stel. Die program kan ook jou netwerkaktiwiteit monitor."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Hierdie toestel word bestuur deur:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJou administrateur is in staat om jou netwerkaktiwiteit te monitor, insluitend e-posse, programme en veilige webwerwe. Kontak jou administrateur vir meer inligting.\n\nJy is ook aan \'n VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") gekoppel. Jou VPN-diensverskaffer kan ook jou netwerkaktiwiteit monitor."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Toestel sal gesluit bly totdat jy dit handmatig ontsluit"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Gedemp deur <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 3174811..9ab4437 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ክፈት"</string>
     <string name="phone_label" msgid="2320074140205331708">"ስልክ ክፈት"</string>
     <string name="camera_label" msgid="7261107956054836961">"ካሜራ ክፈት"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"የመሣሪያ ደህንነት ተረጋግጧል።"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"የመሣሪያ ደህንነት አልተረጋገጠም።"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"የመሣሪያ ደህንነት ተረጋግጧል፣ የእምነት ወኪል ገቢር።"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"የመሣሪያ ደህንነት አልተረጋገጠም፣ የእምነት ወኪል ገቢር።"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"መልክ ማወቅ በማሄድ ላይ፣ የእምነት ወኪል ገቢር።"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"የግቤት ስልት አዝራር ቀይር"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"የተኳኋኝአጉላ አዝራር።"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"አነስተኛውን ማያ ወደ ትልቅ አጉላ።"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ይህ መሣሪያ የሚተዳደረው በ፦\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nየእርስዎ አስተዳዳሪ ኢሜይሎችን፣ መተግበሪያዎችን እና ደህንነታቸው የተጠበቁ ድር ጣቢያዎችን ጨምሮ የአውታረ መረብ እንቅስቃሴዎን መከታተል ይችላል። ተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።\n\nእንዲሁም፣ «<xliff:g id="APPLICATION">%2$s</xliff:g>» አንድ የVPN ግንኙነት እንዲያዋቅር ፍቃድ ሰጥተዋቸዋል። ይህ መተግበሪያም የአውታረ መረብ እንቅስቃሴ መከታተል ይችላል።"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ይህ መሣሪያ የሚተዳደረው በ፦\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nየእርስዎ አስተዳዳሪ ኢሜይሎችን፣ መተግበሪያዎችን እና ደህንነታቸው የተጠበቁ ድር ጣቢያዎችን ጨምሮ የአውታረ መረብ እንቅስቃሴዎን መከታተል ይችላል። ተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።\n\nእንዲሁም ከአንድ VPN («<xliff:g id="APPLICATION">%2$s</xliff:g>») ጋር ተገናኝተዋል። የእርስዎ የVPN አገልግሎት አቅራቢዎም የአውታረ መረብ እንቅስቃሴ መከታተል ይችላል።"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"እራስዎ እስኪከፍቱት ድረስ መሣሪያ እንደተቆለፈ ይቆያል"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"ድምጽ በ<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ተዘግቷል"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 66e5885..e36b49c 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"إلغاء القفل"</string>
     <string name="phone_label" msgid="2320074140205331708">"فتح الهاتف"</string>
     <string name="camera_label" msgid="7261107956054836961">"فتح الكاميرا"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"الجهاز مؤمّن."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"الجهاز غير مؤمّن."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"الجهاز مؤمّن، الوكيل المعتمد نشط."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"الجهاز غير مؤمّن، الوكيل المعتمد نشط."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"اكتشاف الوجه قيد التشغيل، الوكيل المعتمد نشط."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"زر تبديل طريقة الإدخال."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"زر تكبير/تصغير للتوافق."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"استخدام التكبير/التصغير لتحويل شاشة صغيرة إلى شاشة أكبر"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"هذا الجهاز تتم إدارته بواسطة:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nيمكن للمشرف مراقبة نشاط الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب الآمنة. للحصول على مزيد من المعلومات اتصل بالمشرف.\n\nوكذلك، فإنك منحت \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" إذنًا لإعداد الاتصال بالشبكة الظاهرية الخاصة. ويمكن لهذا التطبيق مراقبة نشاط الشبكة أيضًا."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"هذا الجهاز تتم إدارته بواسطة:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nيمكن للمشرف مراقبة نشاط الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب الآمنة. للحصول على مزيد من المعلومات اتصل بالمشرف.\n\nوكذلك، فإنك متصل بالشبكة الظاهرية الخاصة (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). ويمكن لمزوّد خدمة الشبكة الظاهرية الخاصة مراقبة نشاط الشبكة أيضًا."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"سيظل الجهاز مقفلاً إلى أن يتم إلغاء قفله يدويًا"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"تم كتم الصوت بواسطة <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 7c3bfbb..3636316 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloqueja"</string>
     <string name="phone_label" msgid="2320074140205331708">"obre el telèfon"</string>
     <string name="camera_label" msgid="7261107956054836961">"obre la càmera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"El dispositiu està protegit."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"El dispositiu no està protegit."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"El dispositiu està protegit. L\'agent de confiança està activat."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"El dispositiu no està protegit. L\'agent de confiança està activat."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"La detecció facial s\'està executant. L\'agent de confiança està activat."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botó de canvi del mètode d\'entrada."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Amplia menys com més gran sigui la pantalla."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Administrador del dispositiu:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nL\'administrador pot supervisar la teva activitat de xarxa, inclosos els correus electrònics, les aplicacions i els llocs web segurs. Per obtenir més informació, contacta amb l\'administrador.\n\nA més, has donat permís a \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" per configurar una connexió VPN. Aquesta aplicació també pot supervisar l\'activitat de xarxa."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Administrador del dispositiu:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nL\'administrador pot supervisar la teva activitat de xarxa, inclosos els correus electrònics, les aplicacions i els llocs web segurs. Per obtenir més informació, contacta amb l\'administrador.\n\nA més, estàs connectat a una VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). El proveïdor del servei VPN també pot supervisar l\'activitat de xarxa."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositiu continuarà bloquejat fins que no el desbloquegis manualment."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Silenciat per <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 3e04527..09d5cde 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"odemknout"</string>
     <string name="phone_label" msgid="2320074140205331708">"otevřít telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"spustit fotoaparát"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Zařízení je zabezpečeno."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Zařízení není zabezpečeno."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Zařízení je zabezpečeno, agent důvěry je aktivní."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Zařízení není zabezpečeno, agent důvěry je aktivní."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Je spuštěno rozpoznávání obličeje a je aktivní agent důvěry."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačítko přepnutí metody zadávání"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zvětšit menší obrázek na větší obrazovku."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Toto zařízení je spravováno následující organizací:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nSprávce může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a zabezpečených webových stránek. Další informace získáte od svého správce.\n\nNavíc jste aplikaci <xliff:g id="APPLICATION">%2$s</xliff:g> udělili oprávnění k nastavení připojení VPN. Aktivitu v síti může sledovat také tato aplikace."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Toto zařízení je spravováno následující organizací:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nSprávce může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a zabezpečených webových stránek. Další informace získáte od svého správce.\n\nNavíc jste připojeni také k síti VPN (<xliff:g id="APPLICATION">%2$s</xliff:g>). Vaši aktivitu v síti může sledovat také poskytovatel připojení VPN."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Zařízení zůstane uzamčeno, dokud je ručně neodemknete"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Ignorováno stranou <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index ed4bf17..036bbcb 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"lås op"</string>
     <string name="phone_label" msgid="2320074140205331708">"åbn telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"åbn kamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Enheden er sikret."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Enheden er ikke sikret."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Enheden er sikret, trust agent er aktiv."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Enheden er ikke sikret, trust agent er aktiv."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Ansigtsgenkendelse kører, trust agent er aktiv."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Skift indtastningsmetode-knappen."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
@@ -194,7 +189,7 @@
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mere tid."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelygten er slået fra."</string>
-    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelygte er slået til."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelygten er slået til."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelygten er slået fra."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelygten er slået til."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Invertering af farver er slået fra."</string>
@@ -220,8 +215,8 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skærmen er nu låst i stående retning."</string>
     <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"Skærmen roteres nu automatisk."</string>
-    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"Skærmen er nu låst i landskabstilstand."</string>
-    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"Skærmen er nu låst i portrættilstand."</string>
+    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"Skærmen er nu låst i liggende tilstand."</string>
+    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"Skærmen er nu låst i stående tilstand."</string>
     <string name="dessert_case" msgid="1295161776223959221">"Dessertcase"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Denne enhed administreres af:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nDin administrator kan overvåge din netværksaktivitet, f.eks. e-mails, apps og sikre websites. Kontakt administratoren for at få flere oplysninger.\n\nDu gav også \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" tilladelse til at konfigurere en VPN-forbindelse. Denne app kan også overvåge netværksaktiviteten."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Denne enhed administreres af:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nDin administrator kan overvåge din netværksaktivitet, f.eks. e-mails, apps og sikre websites. Kontakt administratoren for at få flere oplysninger.\n\nDu har også forbindelse til et VPN-netværk (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Din VPN-udbyder kan også overvåge netværksaktiviteten."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheden vil forblive låst, indtil du manuelt låser den op"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Lyden blev afbrudt af <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index b8f9bed..bf70d24 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"Entsperren"</string>
     <string name="phone_label" msgid="2320074140205331708">"Telefon öffnen"</string>
     <string name="camera_label" msgid="7261107956054836961">"Kamera öffnen"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Gerät ist gesichert."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Gerät ist nicht gesichert."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Gerät ist gesichert, Trust Agent ist aktiv."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Gerät ist nicht gesichert, Trust Agent ist aktiv."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Gesichtserkennung läuft, Trust Agent ist aktiv."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Schaltfläche zum Ändern der Eingabemethode"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Schaltfläche für Kompatibilitätszoom"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom auf einen größeren Bildschirm"</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Dieses Gerät wird verwaltet von:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nIhr Administrator kann Ihre Netzwerkaktivitäten überwachen, darunter E-Mails, Apps und sichere Websites. Mehr erfahren Sie von Ihrem Administrator.\n\nSie haben zudem \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" gestattet, eine VPN-Verbindung herzustellen. Diese App kann auch Ihre Netzwerkaktivitäten überwachen."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Dieses Gerät wird verwaltet von:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nIhr Administrator kann Ihre Netzwerkaktivitäten überwachen, einschließlich E-Mails, Apps und sicherer Websites. Mehr erfahren Sie von Ihrem Administrator.\n\nSie sind zudem mit einem VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") verbunden. Ihr VPN-Anbieter kann ebenfalls Ihre Netzwerkaktivitäten überwachen."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Das Gerät bleibt gesperrt, bis Sie es manuell entsperren."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Stummgeschaltet durch <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a6dedff..a314cb1 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ξεκλείδωμα"</string>
     <string name="phone_label" msgid="2320074140205331708">"άνοιγμα τηλεφώνου"</string>
     <string name="camera_label" msgid="7261107956054836961">"άνοιγμα φωτογραφικής μηχανής"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Η συσκευή ασφαλίστηκε."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Η συσκευή δεν ασφαλίστηκε."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Η συσκευή ασφαλίστηκε, ο παράγοντας εμπιστοσύνης είναι ενεργός."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Η συσκευή δεν ασφαλίστηκε, ο παράγοντας εμπιστοσύνης είναι ενεργός."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Ανίχνευση προσώπου σε λειτουργία, ο παράγοντας εμπιστοσύνης είναι ενεργός."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Κουμπί εναλλαγής μεθόδου εισόδου"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Κουμπί εστίασης συμβατότητας."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Ζουμ από μικρότερη σε μεγαλύτερη οθόνη."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Η διαχ. της συσκευής γίνεται από:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nΟ διαχειριστής μπορεί να παρακ. τη δραστ. του δικτύου, όπως τα μην. ηλ. ταχυδρ., τις εφαρ. και τους ασφ. ιστότ. Για περισ. πληροφορίες, επικοιν. με το διαχειριστή.\n\nΕπίσης, επιτρέψατε στο \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" να ρυθμίσει σύνδεση VPN. Αυτή η εφαρ. μπορεί να παρακ. τη δραστ. του δικτύου."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Η διαχείριση της συσκευής γίνεται από:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nΟ διαχειριστής μπορεί να παρακολ. τη δραστ. του δικτύου, όπως τα μην. ηλεκ. ταχυδρ., τις εφαρμογές και τους ασφαλείς ιστότοπους. Για περισ. πληροφορίες, επικοιν. με το διαχειριστή.\n\nΕπίσης, είστε συνδεδ. σε VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Ο παροχέας VPN μπορεί να παρακολ. τη δραστ. του δικτύου."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Η συσκευή θα παραμείνει κλειδωμένη έως ότου την ξεκλειδώσετε μη αυτόματα"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Σίγαση από <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index c5713f9..6273bc2 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"open phone"</string>
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Device secured."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Device not secured."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Device secured, trust agent active."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Device not secured, trust agent active."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Face detection running, trust agent active."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"This device is managed by:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps and secure websites. For more information, contact your administrator.\n\nAlso, you gave \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" permission to set up a VPN connection. This app can monitor network activity too."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"This device is managed by:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps and secure websites. For more information, contact your administrator.\n\nAlso, you\'re connected to a VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Your VPN service provider can monitor network activity too."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Muted by <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index c5713f9..6273bc2 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"open phone"</string>
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Device secured."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Device not secured."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Device secured, trust agent active."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Device not secured, trust agent active."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Face detection running, trust agent active."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"This device is managed by:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps and secure websites. For more information, contact your administrator.\n\nAlso, you gave \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" permission to set up a VPN connection. This app can monitor network activity too."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"This device is managed by:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps and secure websites. For more information, contact your administrator.\n\nAlso, you\'re connected to a VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Your VPN service provider can monitor network activity too."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Muted by <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d79cb81..a684b26 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Dispositivo protegido"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Dispositivo no protegido"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Dispositivo protegido, agente de confianza activo"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Dispositivo no protegido, agente de confianza activo"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Detección de rostro en ejecución, agente de confianza activo"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Dispositivo está administrado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nEl administrador puede supervisar la actividad de red (correo electrónico, aplicaciones y sitios web seguros). Para más información, comunícate con el administrador.\n\nY permitiste que \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" configure una VPN. La aplicación también puede supervisar la actividad de red."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Dispositivo administrado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nEl administrador puede supervisar la actividad de red (correo electrónico, aplicaciones y sitios web seguros). Para más información, comunícate con el administrador.\n\nY estás conectado a una VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). El proveedor de servicios de VPN puede supervisar la actividad de red."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositivo permanecerá bloqueado hasta que lo desbloquees manualmente."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Silenciados por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a2ed6a9..5b9c225 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"El dispositivo es seguro."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"El dispositivo no es seguro."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"El dispositivo es seguro, agente de confianza activo."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"El dispositivo no es seguro, agente de confianza activo."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Reconocimiento facial en curso, agente de confianza activo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Este dispositivo está administrado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nTu administrador puede supervisar la actividad de tu red, incluidos correos electrónicos, aplicaciones y sitios web seguros. Para obtener más información, ponte en contacto con tu administrador.\n\nAdemás, has concedido permiso a <xliff:g id="APPLICATION">%2$s</xliff:g> para configurar una red VPN. Esta aplicación también puede supervisar tu red."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Este dispositivo está administrado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nTu administrador puede supervisar la actividad de tu red, incluidos correos electrónicos, aplicaciones y sitios web seguros. Para obtener más información, ponte en contacto con tu administrador.\n\nAdemás, estás conectado a una red VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). El proveedor de servicios de VPN también puede supervisar la actividad de la red."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositivo permanecerá bloqueado hasta que se desbloquee manualmente"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Silenciado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index aea9418..0f11085 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ava lukk"</string>
     <string name="phone_label" msgid="2320074140205331708">"ava telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"ava kaamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Seade on kaitstud."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Seade ei ole kaitstud."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Seade on kaitstud, usaldusväärne agent on aktiivne."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Seade ei ole kaitstud, usaldusväärne agent on aktiivne."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Näotuvastus töötab, usaldusväärne agent on aktiivne."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Sisestusmeetodi vahetamise nupp."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Sobivussuumi nupp."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Suumi suuremale ekraanile vähem."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Seda seadet haldab\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministraator saab jälgida teie võrgutegevust, sh meile, rakendusi ja turvalisi veebisaite. Lisateabe saamiseks võtke ühendust administraatoriga.\n\nLisaks andsite rakendusele „<xliff:g id="APPLICATION">%2$s</xliff:g>” loa seadistada VPN-i ühendus. See rakendus võib ka jälgida teie võrgutegevust."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Seda seadet haldab\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministraator saab jälgida teie võrgutegevust, sh meile, rakendusi ja turvalisi veebisaite. Lisateabe saamiseks võtke ühendust administraatoriga.\n\nSamuti olete ühendatud VPN-iga („<xliff:g id="APPLICATION">%2$s</xliff:g>”). VPN-i teenusepakkuja saab ka teie võrgutegevust jälgida."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Seade jääb lukku, kuni selle käsitsi avate"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> vaigistas"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 81101ee..697963f 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desblokeatu"</string>
     <string name="phone_label" msgid="2320074140205331708">"ireki telefonoan"</string>
     <string name="camera_label" msgid="7261107956054836961">"ireki kamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Gailua babestuta dago."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Gailua ez dago babestuta."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Gailua babestuta dago eta fidagarritasun-agentea aktibo dago."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Gailua ez dago babestuta eta fidagarritasun-agentea aktibo dago."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Aurpegia hautemateko eginbidea abian da eta fidagarritasun-agentea aktibo dago."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Idazketa-metodoa aldatzeko botoia."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoom-bateragarritasunaren botoia."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Handiagotu pantaila txikia."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne.Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexio bat ezartzeko baimena eman diozu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" aplikazioari. Aplikazioak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Gailua blokeatuta egongo da eskuz desblokeatu arte"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> erabiltzaileak audioa desaktibatu du"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 7d689d9..8405d51 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"بازکردن قفل"</string>
     <string name="phone_label" msgid="2320074140205331708">"باز کردن تلفن"</string>
     <string name="camera_label" msgid="7261107956054836961">"باز کردن دوربین"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"دستگاه ایمن شد."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"دستگاه ایمن نشده است."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"دستگاه ایمن شد، نماینده معتمد فعال است."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"دستگاه ایمن نشده است، نماینده معتمد فعال است."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"تشخیص چهره در حال اجرا و نماینده معتمد فعال است."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"کلید تغییر روش ورود متن."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"دکمه بزرگنمایی سازگار."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"بزرگنمایی از صفحه‌های کوچک تا بزرگ."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"‏مدیریت این دستگاه توسط:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nسرپرستتان می‌تواند فعالیت شبکه‌تان را کنترل کند، از جمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌های ایمن. برای کسب اطلاعات بیشتر، با سرپرستتان تماس بگیرید.\n\nهمچنین، به \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" اجازه دادید تا اتصال VPN را تنظیم کند. این برنامه می‌تواند فعالیت شبکه را نیز کنترل کند."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"‏مدیریت این دستگاه توسط:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nسرپرستتان می‌تواند فعالیت شبکه‌تان را کنترل کند از جمله ایمیل‌ها، برنامه‌ها، و وب‌سایت‌های ایمن. برای کسب اطلاعات بیشتر، با سرپرستتان تماس بگیرید.\n\nهمچنین، به VPN‏ ‎‏(\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") وصل هستید. ارائه‌دهنده سرویس VPN شما می‌تواند فعالیت شبکه را نیز کنترل کند."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"دستگاه قفل باقی می‌ماند تا زمانی که قفل آن را به صورت دستی باز کنید"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> آن را بی‌صدا کرد"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index ee4f42e..d7a7720 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -84,22 +84,14 @@
     <string name="accessibility_search_light" msgid="1103867596330271848">"Haku"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
     <string name="accessibility_phone_button" msgid="6738112589538563574">"Puhelin"</string>
-    <!-- no translation found for unlock_label (8779712358041029439) -->
-    <skip />
-    <!-- no translation found for phone_label (2320074140205331708) -->
-    <skip />
-    <!-- no translation found for camera_label (7261107956054836961) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="unlock_label" msgid="8779712358041029439">"avaa lukitus"</string>
+    <string name="phone_label" msgid="2320074140205331708">"avaa puhelin"</string>
+    <string name="camera_label" msgid="7261107956054836961">"avaa kamera"</string>
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Laite on suojattu."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Laitetta ei ole suojattu."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Laite on suojattu. Luotettava taho on aktiivinen."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Laitetta ei ole suojattu. Luotettava taho on aktiivinen."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Kasvojen tunnistus käynnissä. Luotettava taho on aktiivinen."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Syöttötavan vaihtopainike."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Yhteensopivuuszoomaus-painike."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoomaa pienemmältä suuremmalle ruudulle."</string>
@@ -174,65 +166,37 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"Aikaisemmat ruudut."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Käyttäjä: <xliff:g id="USER">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_off (8716484460897819400) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_on (6440117170789528622) -->
-    <skip />
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Wi-Fi otettiin käyttöön."</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobiiliverkkoyhteys: <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akku: <xliff:g id="STATE">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_airplane_off (7786329360056634412) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_on (6406141469157599296) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_off (66846307818850664) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_on (8983005603505087728) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_off (2133631372372064339) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_on (7681999166216621838) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connecting (6953242966685343855) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connected (4306637793614573659) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_off (2730003763480934529) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_on (8722351798763206577) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_off (5119080556976115520) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_on (5809937096590102036) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_off (8526845571503387376) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_on (339403053079338468) -->
-    <skip />
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Lentokonetila on pois päältä."</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Lentokonetila on päällä."</string>
+    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Lentokonetila poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Lentokonetila otettiin käyttöön."</string>
+    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Bluetooth on pois päältä."</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Bluetooth on päällä."</string>
+    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"Bluetoothia yhdistetään."</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth yhdistetty."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"Bluetooth poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"Bluetooth otettiin käyttöön."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Sijainnin ilmoittaminen on pois päältä."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Sijainnin ilmoittaminen on päällä."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"Sijainnin ilmoittaminen poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"Sijainnin ilmoittaminen otettiin käyttöön."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Hälytys asetettu, aika: <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (3115847794692516306) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (3659274935356197708) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (2404728746293515623) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_off (4936432000069786988) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_on (2003479320007841077) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_off (3303701786768224304) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_on (6531793301533894686) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_off (4406577213290173911) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_on (6897462320184911126) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_off (5004708003447561394) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_on (2890951609226476206) -->
-    <skip />
-    <!-- no translation found for accessibility_casting_turned_off (1430668982271976172) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Sulje paneeli"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lisää aikaa."</string>
+    <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Vähennä aikaa."</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taskulamppu on pois päältä."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taskulamppu on päällä."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Taskulamppu poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Taskulamppu otettiin käyttöön."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Käänteiset värit poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Käänteiset värit otettiin käyttöön."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Mobiiliyhteyden hotspot poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobiiliyhteyden hotspot otettiin käyttöön."</string>
+    <string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ruudun lähetys pysäytettiin."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Näytön kirkkaus"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G-tiedonsiirto ei ole käytössä"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-tiedonsiirto ei ole käytössä"</string>
@@ -250,12 +214,9 @@
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ruutu on lukittu vaakasuuntaan."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ruutu on lukittu pystysuuntaan."</string>
-    <!-- no translation found for accessibility_rotation_lock_off_changed (8134601071026305153) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_landscape_changed (3135965553707519743) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_portrait_changed (8922481981834012126) -->
-    <skip />
+    <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"Ruutu kiertyy nyt automaattisesti."</string>
+    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"Ruutu on nyt lukittu vaakasuuntaan."</string>
+    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"Ruutu on nyt lukittu pystysuuntaan."</string>
     <string name="dessert_case" msgid="1295161776223959221">"Jälkiruokavitriini"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Unelmat"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
@@ -378,8 +339,7 @@
     <string name="vpn_footer" msgid="2388611096129106812">"Verkkoa saatetaan valvoa"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"Laitteiden valvonta"</string>
     <string name="monitoring_title" msgid="169206259253048106">"Verkon valvonta"</string>
-    <!-- no translation found for disable_vpn (4435534311510272506) -->
-    <skip />
+    <string name="disable_vpn" msgid="4435534311510272506">"Poista VPN käytöstä"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"Katkaise VPN-yhteys"</string>
     <string name="monitoring_description_device_owned" msgid="7512371572956715493">"Tätä laitetta hallinnoi:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJärjestelmänvalvoja saattaa tarkkailla laitteesi ja verkon toimintaa, kuten sähköposteja, sovelluksia ja turvallisia sivustoja.\n\nKysy lisätietoja järjestelmänvalvojalta."</string>
     <string name="monitoring_description_vpn" msgid="7288268682714305659">"Annoit sovellukselle \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" luvan muodostaa VPN-yhteys.\n\nTämä sovellus saattaa tarkkailla laitteesi ja verkon toimintaa, kuten sähköposteja, sovelluksia ja turvallisia sivustoja."</string>
@@ -387,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Tämän laitteen hallinnoija on \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJärjestelmänvalvoja pystyy valvomaan toimiasi verkossa, esimerkiksi sähköpostin, sovellusten ja turvallisten verkkosivustojen käyttöä. Saat lisätietoja järjestelmänvalvojalta.\n\nAnnoit sovellukselle <xliff:g id="APPLICATION">%2$s</xliff:g> luvan VPN-yhteyden määrittämiseen. Myös se pystyy valvomaan toimiasi verkossa."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Tämän laitteen hallinnoija on \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJärjestelmänvalvoja pystyy valvomaan toimiasi verkossa, esimerkiksi sähköpostin, sovellusten ja turvallisten verkkosivustojen käyttöä. Saat lisätietoja järjestelmänvalvojalta.\n\nLisäksi on muodostettu VPN-yhteys (<xliff:g id="APPLICATION">%2$s</xliff:g>). VPN-palveluntarjoaja voi myös valvoa toimiasi verkossa."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Laite pysyy lukittuna, kunnes se avataan käsin"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Mykistänyt <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index d9d3f50..300c61f 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"déverrouiller"</string>
     <string name="phone_label" msgid="2320074140205331708">"Ouvrir le téléphone"</string>
     <string name="camera_label" msgid="7261107956054836961">"Ouvrir l\'appareil photo"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"L\'appareil est sécurisé."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"L\'appareil n\'est pas sécurisé."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"L\'appareil est sécurisé, l\'agent de confiance est actif."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"L\'appareil n\'est pas sécurisé, l\'agent de confiance est actif."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"La détection de visage est en cours, l\'agent de confiance est actif."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Cet appareil est géré par :\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nVotre administrateur peut surveiller votre activité réseau, y compris les courriels, les applications et les sites Web sécurisés. Pour en savoir plus à ce sujet, communiquez avec votre administrateur réseau.\n\nVous avez aussi autorisé « <xliff:g id="APPLICATION">%2$s</xliff:g> » à créer une connexion RPV. Cette application peut aussi surveiller votre activité réseau."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Cet appareil est géré par :\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nVotre administrateur peut surveiller votre activité (courriels, applications, sites Web sécurisés, etc.). Pour en savoir plus, communiquez avec votre administrateur.\n\nVous êtes également connecté à un RPV (<xliff:g id="APPLICATION">%2$s</xliff:g>). Votre fournisseur RPV peut aussi surveiller votre activité réseau."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Mis en sourdine par <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 9a068e8..60aff3a 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Dispositivo protexido."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Dispositivo non protexido."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Dispositivo protexido, axente de confianza activo."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Dispositivo non protexido, axente de confianza activo."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Recoñecemento facial en curso, axente de confianza activo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Cambiar o botón do método de entrada."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidade"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilidade co tamaño da pantalla."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Este dispositivo está xestionado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nO teu administrador pode supervisar a actividade da túa rede, incluídos os correos electrónicos, as aplicacións e os sitios web seguros. Para obter máis información, contacta co teu administrador.\n\nAdemais, outorgaches permiso a \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" para configurar unha conexión VPN. Esta aplicación tamén pode supervisar a actividade da rede."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Este dispositivo está xestionado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nO teu administrador pode supervisar a actividade da túa rede, incluídos os correos electrónicos, as aplicacións e os sitios web seguros. Para obter máis información, contacta co teu administrador.\n\nAdemais, estás conectado a unha VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). O fornecedor de servizos da VPN tamén pode supervisar a actividade da rede."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado ata que o desbloquees manualmente"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Silenciado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index fe4322f..6f43a2e 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"अनलॉक करें"</string>
     <string name="phone_label" msgid="2320074140205331708">"फ़ोन खोलें"</string>
     <string name="camera_label" msgid="7261107956054836961">"कैमरा खोलें"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"उपकरण सुरक्षित है."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"उपकरण सुरक्षित नहीं है."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"उपकरण सुरक्षित है, विश्वसनीय एजेंट सक्रिय है."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"उपकरण सुरक्षित नहीं है, विश्वसनीय एजेंट सक्रिय है."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"चेहरा पहचान सुविधा चल रही है, विश्वसनीय एजेंट सक्रिय है."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति‍ बटन स्विच करें."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्‍क्रीन पर ज़ूम करें."</string>
@@ -171,20 +166,20 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"हाल ही की स्‍क्रीन."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"उपयोगकर्ता <xliff:g id="USER">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
-    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi को बंद किया गया."</string>
-    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Wifi को चालू किया गया."</string>
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"वाई-फ़ाई को बंद किया गया."</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"वाई-फ़ाई को चालू किया गया."</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"मोबाइल <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"बैटरी <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"हवाई जहाज़ मोड बंद है."</string>
     <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"हवाई जहाज़ मोड चालू है."</string>
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"हवाई जहाज़ मोड को बंद किया गया."</string>
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"हवाई जहाज़ मोड को चालू किया गया."</string>
-    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Bluetooth बंद है."</string>
-    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Bluetooth चालू है."</string>
-    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"Bluetooth कनेक्‍ट हो रहा है."</string>
-    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth कनेक्ट है."</string>
-    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"Bluetooth को बंद किया गया."</string>
-    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"Bluetooth को चालू किया गया."</string>
+    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"ब्लूटूथ बंद है."</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"ब्लूटूथ चालू है."</string>
+    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"ब्लूटूथ कनेक्‍ट हो रहा है."</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"ब्लूटूथ कनेक्ट है."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"ब्लूटूथ को बंद किया गया."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"ब्लूटूथ को चालू किया गया."</string>
     <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"स्‍थान रिपोर्टिंग बंद है."</string>
     <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"स्‍थान रिपोर्टिंग चालू है."</string>
     <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"स्‍थान रिपोर्टिंग को बंद किया गया."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"यह उपकरण इसके द्वारा प्रबंधित है:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपका व्‍यवस्‍थापक ईमेल, ऐप्‍स और सुरक्षित वेबसाइटों सहित आपकी नेटवर्क गतिविधि को मॉनीटर कर सकता है. अधिक जानकारी के लिए, अपने व्‍यवस्‍थापक से संपर्क करें.\n\nसाथ ही, आपने VPN कनेक्‍शन सेट करने के लिए \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" अनुमति भी दी है. यह ऐप्‍स नेटवर्क गतिविधि को भी मॉनीटर कर सकता है."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"यह उपकरण इसके द्वारा प्रबंधित है:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपका व्‍यवस्‍थापक, ईमेल, ऐप्‍स और सुरक्षित वेबसाइटों सहित आपकी नेटवर्क गतिविधि को मॉनीटर कर सकता है. अधिक जानकारी के लिए, अपने व्‍यवस्‍थापक से संपर्क करें.\n\nसाथ ही, आप VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") से कनेक्‍ट हैं. आपका VPN सेवा प्रदाता नेटवर्क गतिविधि को भी मॉनीटर कर सकता है."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"जब तक कि आप मैन्‍युअल रूप से अनलॉक नहीं करते तब तक उपकरण लॉक रहेगा"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा म्यूट किया गया"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index fe4dd53..53aca5e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"otključavanje"</string>
     <string name="phone_label" msgid="2320074140205331708">"otvaranje telefona"</string>
     <string name="camera_label" msgid="7261107956054836961">"otvaranje fotoaparata"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Uređaj je zaštićen."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Uređaj nije zaštićen."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Uređaj je zaštićen, agent za pouzdanost je aktivan."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Uređaj nije zaštićen, agent za pouzdanost je aktivan."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Prepoznavanje lica je u tijeku, agent za pouzdanost je aktivan."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za promjenu načina unosa."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb za kompatibilnost zumiranja."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje manjeg zaslona na veći."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Uređajem upravlja:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nVaš administrator može pratiti vašu aktivnost na mreži, uključujući e-poštu, aplikacije i sigurne web-lokacije. Više informacija možete saznati od administratora.\n\nOsim toga, dali ste aplikaciji \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" dopuštenje za postavljanje VPN veze, pa i ona može pratiti vašu aktivnost na mreži."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Uređajem upravlja:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nVaš administrator može pratiti vašu aktivnost na mreži, uključujući e-poštu, aplikacije i sigurne web-lokacije. Više informacija možete saznati od administratora.\n\nOsim toga, povezani ste s VPN-om (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Davatelj usluge VPN-a također može pratiti vašu aktivnost na mreži."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ručno ne otključate"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Zvuk je isklj. treća strana <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 4dafd7f..5a4619f 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"feloldás"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefon megnyitása"</string>
     <string name="camera_label" msgid="7261107956054836961">"kamera megnyitása"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Az eszköz biztosítva van."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Az eszköz nincs biztosítva."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Az eszköz biztosítva van, a trust agent komponens aktív."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Az eszköz nincs biztosítva, a trust agent komponens aktív."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Az arcfelismerés fut, a trust agent komponens aktív."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Beviteli mód váltása gomb."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kompatibilitási zoom gomb."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kicsinyítsen a nagyobb képernyőhöz."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Ezt az eszközt a következő felügyeli:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nA rendszergazda figyelheti a hálózati tevékenységet, beleértve az e-mailt, az alkalmazásokat és a biztonságos webhelyeket. További információért forduljon a rendszergazdához.\n\nEzenfelül engedélyt adott „<xliff:g id="APPLICATION">%2$s</xliff:g>” számára VPN-kapcsolat beállítására. Ez az alkalmazás is figyelheti a hálózati tevékenységet."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Ezt az eszközt a következő felügyeli:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nA rendszergazda figyelheti a hálózati tevékenységet, beleértve az e-mailt, az alkalmazásokat és a biztonságos webhelyeket. További információért forduljon a rendszergazdához.\n\nEzenfelül VPN-hez is csatlakozik („<xliff:g id="APPLICATION">%2$s</xliff:g>”). VPN-szolgáltatója is figyelheti hálózati tevékenységét."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Az eszköz addig zárolva marad, amíg kézileg fel nem oldja"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"A(z) <xliff:g id="THIRD_PARTY">%1$s</xliff:g> elnémította"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index e538d14c..09e5f72 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ապակողպել"</string>
     <string name="phone_label" msgid="2320074140205331708">"բացել հեռախոսը"</string>
     <string name="camera_label" msgid="7261107956054836961">"բացել ֆոտոխցիկը"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Սարքը պաշտպանված է:"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Սարքը պաշտպանված չէ:"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Սարքը պաշտպանված է, վստահության գործակալն ակտիվ  է:"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Սարքը պաշտպանված չէ, վստահության գործակալն ակտիվ  է:"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Կատարվում է դիմաճանաչում, վստահության գործակալն ակտիվ է:"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Այս սարքը կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nՁեր ադմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:\n\n Բացի այդ, դուք «<xliff:g id="APPLICATION">%2$s</xliff:g>» ծրագրին թույլատրել եք ստեղծել VPN կապ: Այդ ծրագիրը նույնպես կարող է վերահսկել ձեր ցանցային գործունեությունը:"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Այս սարքը կառավարիչն է՝\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nՁեր ադմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ձեր ադմինիստրատորին:\n\nԲացի այդ, դուք միացած եք VPN-ին («<xliff:g id="APPLICATION">%2$s</xliff:g>»): Ձեզ VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Սարքը կմնա արգելափակված՝ մինչև ձեռքով չբացեք"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Համրեցվել է <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ի կողմից"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 5cf0125..10c8e17 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"buka kunci"</string>
     <string name="phone_label" msgid="2320074140205331708">"buka ponsel"</string>
     <string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Perangkat aman."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Perangkat tidak aman."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Perangkat aman, agen tepercaya aktif."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Perangkat tidak aman, agen tepercaya aktif."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Deteksi wajah berjalan, agen tepercaya aktif."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tombol beralih metode masukan."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tombol perbesar/perkecil kompatibilitas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Perbesar dari layar kecil ke besar."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Perangkat ini dikelola oleh:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministrator Anda dapat memantau aktivitas jaringan termasuk email, aplikasi, dan situs web aman. Untuk informasi selengkapnya, hubungi administrator Anda.\n\nAnda juga memberikan izin pada \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" untuk menyiapkan sambungan VPN. Aplikasi ini juga memantau aktivitas jaringan."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Perangkat ini dikelola oleh:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministrator Anda dapat memantau aktivitas jaringan termasuk email, aplikasi, dan situs web aman. Untuk informasi selengkapnya, hubungi administrator Anda.\n\nAnda juga tersambung ke VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Penyedia layanan VPN Anda dapat memantau aktivitas jaringan juga."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Perangkat akan tetap terkunci hingga Anda membukanya secara manual"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Dinonaktifkan oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index ed8dcb0..ef67d1b 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"taka úr lás"</string>
     <string name="phone_label" msgid="2320074140205331708">"opna síma"</string>
     <string name="camera_label" msgid="7261107956054836961">"opna myndavél"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Tæki öruggt."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Tæki ekki öruggt."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Tæki öruggt; traustfulltrúi virkur."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Tæki ekki öruggt; traustfulltrúi virkur."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Andlitsgreining í gangi; traustfulltrúi virkur."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Hnappur til að skipta um innsláttaraðferð."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Hnappur fyrir samhæfisaðdrátt."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aðlaga forrit fyrir lítinn skjá að stærri skjá."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Stjórnandi þessa tækis er:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nStjórnandinn getur fylgst með netvirkni þinni, þ. á m. tölvupósti, forritum og öruggum vefsvæðum. Hafðu samband við stjórnandann til að fá frekari upplýsingar.\n\nÞú veittir „<xliff:g id="APPLICATION">%2$s</xliff:g>“ einnig  heimild til að setja upp VPN-tengingu. Þetta forrit getur líka fylgst með netvirkni þinni."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Stjórnandi þessa tækis er:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nStjórnandinn getur fylgst með netvirkni þinni, þ. á m. tölvupósti, forritum og öruggum vefsvæðum. Hafðu samband við stjórnandann til að fá frekari upplýsingar.\n\nÞú ert einnig tengd(ur) VPN-neti („<xliff:g id="APPLICATION">%2$s</xliff:g>“). VPN-þjónustuaðilinn þinn getur líka fylgst með netvirkni þinni."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Tækið verður læst þar til þú opnar það handvirkt"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> tók hljóðið af"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 5b79d15..f74c2c7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"sblocca"</string>
     <string name="phone_label" msgid="2320074140205331708">"apri telefono"</string>
     <string name="camera_label" msgid="7261107956054836961">"apri fotocamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Dispositivo protetto."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Dispositivo non protetto."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Dispositivo protetto, agente di attendibilità attivo."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Dispositivo non protetto, agente di attendibilità attivo."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Rilevamento del viso in esecuzione, agente di attendibilità attivo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Pulsante per cambiare metodo di immissione."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom inferiore per schermo più grande."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Il dispositivo è gestito da:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nIl tuo amministratore può monitorare la tua attività di rete, inclusi email, app e siti web protetti. Per ulteriori informazioni, contatta l\'amministratore.\n\nInoltre, hai autorizzato \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" a configurare una connessione VPN. Questa app può monitorare anche l\'attività di rete."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Il dispositivo è gestito da:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nIl tuo amministratore può monitorare la tua attività di rete, inclusi email, app e siti web protetti. Per ulteriori informazioni, contatta l\'amministratore.\n\nInoltre, sei collegato a una rete VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Il tuo provider di servizi VPN può monitorare anche l\'attività di rete."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Il dispositivo resterà bloccato fino allo sblocco manuale"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Audio disattivato da <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 741755a..124ddcb 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"בטל את הנעילה"</string>
     <string name="phone_label" msgid="2320074140205331708">"פתח את הטלפון"</string>
     <string name="camera_label" msgid="7261107956054836961">"פתח את המצלמה"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"המכשיר מאובטח."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"המכשיר אינו מאובטח."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"המכשיר מאובטח, סביבה אמינה פעילה."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"המכשיר אינו מאובטח, סביבה אמינה פעילה."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"זיהוי פנים פועל, סביבה אמינה פעילה."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"לחצן החלפת שיטת קלט."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"לחצן מרחק מתצוגה של תאימות."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"שנה מרחק מתצוגה של מסך קטן לגדול יותר."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"‏מכשיר זה מנוהל על ידי:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nמנהל המערכת שלך יכול לעקוב אחר הפעילות שלך ברשת, כולל הודעות דוא\"ל, אפליקציות, ואתרים מאובטחים. למידע נוסף, צור קשר עם מנהל המערכת שלך.\n\nכמו כן, נתת ל-\"<xliff:g id="APPLICATION">%2$s</xliff:g>\" הרשאה להגדרת חיבור VPN. גם אפליקציה זו יכולה לעקוב אחר הפעילות שלך ברשת."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"‏מכשיר זה מנוהל על ידי:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nמנהל המערכת שלך יכול לעקוב אחר הפעילות שלך ברשת, כולל הודעות דוא\"ל, אפליקציות, ואתרים מאובטחים. למידע נוסף, צור קשר עם מנהל המערכת שלך.\n\nכמו כן, אתה מחובר ל-VPN ‏‏(\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). גם ספק שירות ה-VPN שלך יכול לעקוב אחר הפעילות שלך ברשת."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"המכשיר יישאר נעול עד שתבטל את נעילתו באופן ידני"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"הושתק על ידי <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index e1d41fb..edc7009 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ロック解除"</string>
     <string name="phone_label" msgid="2320074140205331708">"電話を起動"</string>
     <string name="camera_label" msgid="7261107956054836961">"カメラを起動"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"端末は保護されています。"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"端末は保護されていません。"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"端末は保護され、信頼できるエージェントがアクティブです。"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"端末は保護されておらず、信頼できるエージェントがアクティブです。"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"顔検出を実行しており、信頼できるエージェントがアクティブです。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"入力方法の切り替えボタン。"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"互換ズームボタン。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"小さい画面から大きい画面に拡大。"</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"この端末は<xliff:g id="ORGANIZATION">%1$s</xliff:g>によって管理されています。\n\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、「<xliff:g id="APPLICATION">%2$s</xliff:g>」にVPN接続のセットアップを許可しています。このアプリもネットワークアクティビティを監視できます。"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"この端末は<xliff:g id="ORGANIZATION">%1$s</xliff:g>によって管理されています。\n\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%2$s</xliff:g>」)に接続しています。VPNサービスプロバイダーもネットワークアクティビティを監視できます。"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"手動でロックを解除するまでロックされたままとなります"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>によりミュートになっています"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 6e44eb5..facbd12d 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -84,22 +84,14 @@
     <string name="accessibility_search_light" msgid="1103867596330271848">"ძიება"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"კამერა"</string>
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ტელეფონი"</string>
-    <!-- no translation found for unlock_label (8779712358041029439) -->
-    <skip />
-    <!-- no translation found for phone_label (2320074140205331708) -->
-    <skip />
-    <!-- no translation found for camera_label (7261107956054836961) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="unlock_label" msgid="8779712358041029439">"განბლოკვა"</string>
+    <string name="phone_label" msgid="2320074140205331708">"ტელეფონის გახსნა"</string>
+    <string name="camera_label" msgid="7261107956054836961">"კამერის გახსნა"</string>
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"მოწყობილობა დაცულია."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"მოწყობილობა არ არის დაცული."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"მოწყობილობა დაცულია, ნდობის აგენტი აქტიურია."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"მოწყობილობა არ არის დაცული, ნდობის აგენტი აქტიურია."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"მიმდინარეობს სახის ამოცნობა, ნდობის აგენტი აქტიურია."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"თავსებადი მასშტაბირების ღილაკი."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"შეცვალეთ პატარა ეკრანი უფრო დიდით."</string>
@@ -174,65 +166,37 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"ბოლო ეკრანები."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"მომხმარებელი: <xliff:g id="USER">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_off (8716484460897819400) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_on (6440117170789528622) -->
-    <skip />
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi გამორთულია."</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Wifi ჩართულია."</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"მობილურის <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ელემენტი: <xliff:g id="STATE">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_airplane_off (7786329360056634412) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_on (6406141469157599296) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_off (66846307818850664) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_on (8983005603505087728) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_off (2133631372372064339) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_on (7681999166216621838) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connecting (6953242966685343855) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connected (4306637793614573659) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_off (2730003763480934529) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_on (8722351798763206577) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_off (5119080556976115520) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_on (5809937096590102036) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_off (8526845571503387376) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_on (339403053079338468) -->
-    <skip />
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"თვითმფრინავის რეჟიმი გამორთულია."</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"თვითმფრინავის რეჟიმი ჩართულია."</string>
+    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"თვითმფრინავის რეჟიმი გამოირთო."</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"თვითმფრინავის რეჟიმი ჩაირთო."</string>
+    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Bluetooth გამორთულია."</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Bluetooth ჩართულია."</string>
+    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"მიმდინარეობს Bluetooth-თან დაკავშირება."</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth დაკავშირებულია."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"Bluetooth გამოირთო."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"Bluetooth ჩაირთო."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"მდებარეობის შეტყობინება გამორთულია."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"მდებარეობის შეტყობინება ჩართულია."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"მდებარეობის შეტყობინება გამოირთო."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"მდებარეობის შეტყობინება ჩაირთო."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"მაღვიძარა დაყენებულია: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <!-- no translation found for accessibility_quick_settings_close (3115847794692516306) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (3659274935356197708) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (2404728746293515623) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_off (4936432000069786988) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_on (2003479320007841077) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_off (3303701786768224304) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_on (6531793301533894686) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_off (4406577213290173911) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_on (6897462320184911126) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_off (5004708003447561394) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_on (2890951609226476206) -->
-    <skip />
-    <!-- no translation found for accessibility_casting_turned_off (1430668982271976172) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"არეს დახურვა."</string>
+    <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"მეტი დრო."</string>
+    <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ნაკლები დრო."</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ფანარი გამორთულია."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ფანარი ჩართულია."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ფანარი გამოირთო."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ფანარი ჩაირთო."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"ფერის ინვერსია გამოირთო."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"ფერის ინვერსია ჩაირთო."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"მობილური ქსელის წერტილი გამოირთო."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"მობილური ქსელის წერტილი ჩაირთო."</string>
+    <string name="accessibility_casting_turned_off" msgid="1430668982271976172">"ეკრანის გადაცემა შეჩერებულია."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"ეკრანის სიკაშკაშე"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G მონაც. გადაცემა გამორთულია"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G მონაც. გადაცემა გამორთულია"</string>
@@ -250,12 +214,9 @@
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ეკრანი შეტრიალდება ავტომატურად."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ეკრანი დაბლოკილია თარაზულ ორიენტაციაში"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ეკრანი დაბლოკილია პორტრეტის ორიენტაციაში."</string>
-    <!-- no translation found for accessibility_rotation_lock_off_changed (8134601071026305153) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_landscape_changed (3135965553707519743) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_portrait_changed (8922481981834012126) -->
-    <skip />
+    <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"ეკრანი უკვე ავტომატურად შეტრიალდება."</string>
+    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"ეკრანი ამჟამად ჩაკეტილია ლანდშაფტის ორიენტაციაზე."</string>
+    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"ეკრანი ამჟამად ჩაკეტილია პორტრეტის ორიენტაციაზე."</string>
     <string name="dessert_case" msgid="1295161776223959221">"სადესერტო ყუთი"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ეთერნეტი"</string>
@@ -376,8 +337,7 @@
     <string name="vpn_footer" msgid="2388611096129106812">"შესაძლოა ქსელზე ხორციელდება მონიტორინგი"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"მოწყობილობის მონიტორინგი"</string>
     <string name="monitoring_title" msgid="169206259253048106">"ქსელის მონიტორინგი"</string>
-    <!-- no translation found for disable_vpn (4435534311510272506) -->
-    <skip />
+    <string name="disable_vpn" msgid="4435534311510272506">"VPN-ის გაუქმება"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN-ის გათიშვა"</string>
     <string name="monitoring_description_device_owned" msgid="7512371572956715493">"ამ მოწყობილობის მმართველი არის:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების.\n\nდამატებითი ინფორმაციისათვის, დაუკავშირდით თქვენს ადმინისტრატორს."</string>
     <string name="monitoring_description_vpn" msgid="7288268682714305659">"თქვენ მიეცით ნებართვა „<xliff:g id="APPLICATION">%1$s</xliff:g>“-ს დააყენოს VPN კავშირი.\n\nამ აპს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების."</string>
@@ -385,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით თქვენს ადმინისტრატორს.\n\nთქვენ მიეცით ნებართვა „<xliff:g id="APPLICATION">%2$s</xliff:g>“-ს დააყენოს VPN კავშირი. ამ აპს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ამ მოწყობილობის მმართველი არის:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტების, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით თქვენს ადმინისტრატორს.\n\nასევე, თქვენ დაკავშირებული ხართ VPN-თან („<xliff:g id="APPLICATION">%2$s</xliff:g>“). თქვენს VPN სერვისის პროვაიდერს ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"მოწყობილობის დარჩება ჩაკეტილი, სანამ ხელით არ გახსნით"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"დადუმებულია <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ის მიერ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 04fd073..acbe587 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"бекітпесін ашу"</string>
     <string name="phone_label" msgid="2320074140205331708">"телефонды ашу"</string>
     <string name="camera_label" msgid="7261107956054836961">"камераны ашу"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Құрылғы қорғалған."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Құрылғы қорғалмаған."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Құрылғы қорғалған, сенімді агент белсенді."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Құрылғы қорғалмаған, сенімді агент белсенді."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Бетті анықтау орындалуда, сенімді агент белсенді."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Енгізу әдісі түймесін ауыстыру."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Үйлесімділік ұлғайту түймесі."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Үлкендеу экранда кішірейту."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Бұл құр. келесі ұйым бас.:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nӘкімші желілік белсенділікті, соның ішінде, электрондық хаб-ды, қолд-ды және қорғалған веб-сайттарды бақ. мүмкін. Қосымша ақпарат алу үшін әкімшіге хабарласыңыз.\n\nСондай-ақ, сіз «<xliff:g id="APPLICATION">%2$s</xliff:g>» қолд-на VPN байланысын орнатуға рұқсат еттіңіз. Бұл қолд. да желілік белс-ті бақылауы мүмкін."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Бұл құрылғыны келесі ұйым басқарады:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nӘкімші желілік белсенділікті, соның ішінде, электрондық хабарларды, қолданбаларды және қорғалған веб-сайттарды бақылауы мүмкін. Қосымша ақпарат алу үшін әкімшіге хабарласыңыз.\n\nСондай-ақ, сіз VPN («<xliff:g id="APPLICATION">%2$s</xliff:g>») желісіне қосылғансыз. VPN қызмет жет-сі де жел. белс-ті бақ. мүм."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Қолмен бекітпесін ашқанша құрылғы бекітілген күйде қалады"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> үнін өшірген"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 380105b..f8cf9ff 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ដោះ​សោ"</string>
     <string name="phone_label" msgid="2320074140205331708">"បើក​ទូរស័ព្ទ"</string>
     <string name="camera_label" msgid="7261107956054836961">"បើក​ម៉ាស៊ីន​ថត"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"ឧបករណ៍​មាន​សុវត្ថិភាព។"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"ឧបករណ៍​គ្មាន​សុវត្ថិភាព។"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"ឧបករណ៍​មាន​សុវត្ថិភាព, ភ្នាក់ងារ​ទុកចិត្ត​សកម្ម។"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"ឧបករណ៍​គ្មាន​សុវត្ថិភាព, ភ្នាក់ងារ​ទុកចិត្ត​សកម្ម។"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"កំពុង​ដំណើរការ​រក​ឃើញ​ទម្រង់​មុខ, ភ្នាក់ងារ​ទុកចិត្ត​សកម្ម។"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរ​ប៊ូតុង​វិធីសាស្ត្រ​បញ្ចូល។"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ពង្រីក/បង្រួម​​អេក្រង់​ពី​​ទៅធំ"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ​ \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n អ្នកគ្រប់គ្រងរបស់អ្នកមានសមត្ថភាពក្នុងការត្រួតពិនិត្យសកម្មភាពបណ្ដាញរបស់អ្នក រួមមានអ៊ីមែល​, កម្មវិធី​, និងតំបន់បណ្ដាញសុវត្ថិភាព​។ សម្រាប់ព័ត៌មានបន្ថែមសូមទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក​។ \n\n អ្នកបានផ្ដល់សិទ្ធិ\"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ដើម្បីរៀបចំការតភ្ជាប់ VPN ។ កម្មវិធីនេះអាចតាមដានសកម្មភាពបណ្ដាញ។"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n អ្នកគ្រប់គ្រងរបស់អ្នកមានសមត្ថភាពក្នុងការត្រួតពិនិត្យសកម្មភាពបណ្ដាញរបស់អ្នករួមមានអ៊ីមែល​, កម្មវិធី និងតំបន់បណ្ដាញសុវត្ថិភាព។ សម្រាប់ព័ត៌មានបន្ថែមសូមទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក។ \n\n ​អ្នកត្រូវបានតភ្ជាប់ទៅ VPN (\" <xliff:g id="APPLICATION">%2$s</xliff:g> \") ។ ក្រុមហ៊ុនផ្ដល់​សេវា VPN របស់អ្នកអាចតាមដានសកម្មភាពរបស់​អ្នក។"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ឧបករណ៍​នឹង​ចាក់​សោ​រហូត​ដល់​អ្នក​ដោះ​សោ​ដោយ​ដៃ"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"បាន​បិទ​សំឡេង​ដោយ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 4457383..63b5156 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ಅನ್‌ಲಾಕ್ ಮಾಡು"</string>
     <string name="phone_label" msgid="2320074140205331708">"ಫೋನ್ ತೆರೆಯಿರಿ"</string>
     <string name="camera_label" msgid="7261107956054836961">"ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"ಸಾಧನವು ಸುರಕ್ಷಿತವಾಗಿದೆ."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"ಸಾಧನವು ಸುರಕ್ಷಿತವಾಗಿಲ್ಲ."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"ಸಾಧನವು ಸುರಕ್ಷಿತವಾಗಿದೆ, ವಿಶ್ವಾಸಾರ್ಹ ಏಜೆಂಟ್ ಸಕ್ರಿಯವಾಗಿದೆ."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"ಸಾಧನವು ಸುರಕ್ಷಿತವಾಗಿಲ್ಲ, ವಿಶ್ವಾಸಾರ್ಹ ಏಜೆಂಟ್ ಸಕ್ರಿಯವಾಗಿದೆ."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"ಮುಖ ಪತ್ತೆಹಚ್ಚುವಿಕೆಯು ರನ್‌ ಆಗುತ್ತಿದೆ, ವಿಶ್ವಾಸಾರ್ಹ ಏಜೆಂಟ್ ಸಕ್ರಿಯವಾಗಿದೆ."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ಇನ್‌ಪುಟ್ ವಿಧಾನ ಬದಲಿಸು ಬಟನ್."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ಹೊಂದಾಣಿಕೆಯ ಝೂಮ್ ಬಟನ್."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ಚಿಕ್ಕ ಪರದೆಯಿಂದ ದೊಡ್ಡ ಪರದೆಗೆ ಝೂಮ್ ಮಾಡು."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ಇವರು ಈ ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸುತ್ತಾರೆ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಮತ್ತು ಸುರಕ್ಷಿತ ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು. ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.\n\nಅಲ್ಲದೇ, ನೀವು VPN ಸಂಪರ್ಕ ಹೊಂದಿಸಲು \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ಗೆ ಅನುಮತಿ ನೀಡಿರುವಿರಿ. ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಸಹ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ಇವರು ಈ ಸಾಧನವನ್ನು ಇವರು ನಿರ್ವಹಿಸುತ್ತಾರೆ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಮತ್ತು ಸುರಕ್ಷಿತ ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು. ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.\n\nಅಲ್ಲದೇ, ನೀವು VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ. ನಿಮ್ಮ VPN ಸೇವೆ ಒದಗಿಸುವವರು ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಸಹ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ನೀವಾಗಿಯೇ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವವರೆಗೆ ಸಾಧನವು ಲಾಕ್‌ ಆಗಿಯೇ ಇರುತ್ತದೆ"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ಅವರಿಂದ ಮ್ಯೂಟ್‌ ಮಾಡಲಾಗಿದೆ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 9b7e67e..c63d040 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -89,16 +89,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"잠금 해제"</string>
     <string name="phone_label" msgid="2320074140205331708">"휴대전화 열기"</string>
     <string name="camera_label" msgid="7261107956054836961">"카메라 열기"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"기기에 보안 설정이 되어 있습니다."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"기기에 보안 설정이 되어 있지 않습니다."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"기기에 보안 설정이 되었으며 Trust Agent가 활성화되어 있습니다."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"기기에 보안 설정이 되어 있지 않으며 Trust Agent가 활성화되어 있습니다."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"얼굴 인식 기능이 실행 중이며 Trust Agent가 활성화되어 있습니다."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"입력 방법 버튼을 전환합니다."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"호환성 확대/축소 버튼입니다."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"작은 화면을 큰 화면으로 확대합니다."</string>
@@ -187,7 +182,7 @@
     <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"블루투스가 연결되었습니다."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"블루투스가 사용 중지되었습니다."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"블루투스를 사용합니다."</string>
-    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"위치 정보 전송: 사용 중지"</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"위치 정보 전송: 사용 안함"</string>
     <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"위치 정보 전송: 사용"</string>
     <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"위치 정보 전송이 사용 중지되었습니다."</string>
     <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"위치 정보 전송을 사용합니다."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"이 기기는 \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>에서 관리합니다.\n\n관리자가 이메일, 앱, 보안 웹사이트 등의 네트워크 활동을 모니터링할 수 있습니다. 자세한 정보는 관리자에게 문의하세요.\n\n또한 \'<xliff:g id="APPLICATION">%2$s</xliff:g>\'에 VPN 연결을 설정할 수 있는 권한을 부여했습니다. 이 앱에서도 네트워크 활동을 모니터링할 수 있습니다."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"이 기기는 \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>에서 관리합니다.\n\n관리자가 이메일, 앱, 보안 웹사이트 등의 네트워크 활동을 모니터링할 수 있습니다. 자세한 정보는 관리자에게 문의하세요.\n\n또한 VPN에도 연결되었습니다(\'<xliff:g id="APPLICATION">%2$s</xliff:g>\'). VPN 서비스 제공업체에서도 네트워크 활동을 모니터링할 수 있습니다."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"수동으로 잠금 해제할 때까지 기기가 잠금 상태로 유지됩니다."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>에서 알림음 음소거"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index b9ee3d4..d66f619 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -113,16 +113,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"кулпуну ачуу"</string>
     <string name="phone_label" msgid="2320074140205331708">"телефонду ачуу"</string>
     <string name="camera_label" msgid="7261107956054836961">"камераны ачуу"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Түзмөк корголгон."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Түзмөк кооптуу."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Түзмөк корголгон, ишеним агенти иштеп турат."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Түзмөк кооптуу, ишеним агенти иштеп турат."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Жүз аныктоо мүмкүнчүлүгү иштеп жатат, ишенимдүү агенти активдүү."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Киргизүү ыкмасын которуу баскычы."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Масштабды сыйыштыруу баскычы."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Кичинекейди чоң экранга масштабдоо."</string>
@@ -376,6 +371,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Бул түзмөк төмөнкүчө башкарылат:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдминистратор электрондук почталар, колдонмолор жана коопсуз вебсайттар сыяктуу тармактгы аракеттрге көз салып турт. Көбүрөөк билүү үчн, администратрго кайрылңз.\n\nОшондой эле \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" VPN туташуусн орнотууга урукст бердиңз. Бул колдонмо тармактгы аракеттерңзге дагы көз салат."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Бул түзмөк төмөнкүчө башкарылат:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдминистратор электрондук почта, колдонмолор жана коопсуз вебсайттар сыяктуу тармактагы аракеттериңизге көз салып турат. Көбүрөөк билүү үчүн, администраторго кайрылыңыз.\n\nОшондой эле VPN\'ге туташып турасыз. (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN кызмат көрсөтүүчү тармактагы аракетиңизге көз салат."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Түзмөктүн кулпусу кол менен ачылмайынча кулпуланган бойдон алат"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> тарабынан үнсүздөлдү"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index d212f14..13cfbef 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ປົດລັອກ"</string>
     <string name="phone_label" msgid="2320074140205331708">"​ເປີດ​​ແປ້ນ​ໂທ​ລະ​ສັບ"</string>
     <string name="camera_label" msgid="7261107956054836961">"ເປີດ​ກ້ອງ"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"ອຸ​ປະ​ກອນ​ປອດ​ໄພ​ແລ້ວ."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"ອ​ຸ​ປະ​ກອນບໍ່​ປອດ​ໄພ."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"ອຸ​ປະ​ກອນ​ປອດ​ໄພ​ແລ້ວ, ຕົວ​ແທນ​ທີ່​ເຊື່ອ​ຖື​ໄດ້​ຖືກ​ເປີດ​ໃຊ້."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"ອ​ຸ​ປະ​ກອນບໍ່​ປອດ​ໄພ, ຕົວ​ແທນ​ທີ່​ເຊື່ອ​ຖື​ໄດ້​ຖືກ​ເປີດ​ໃຊ້."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"ການກວດ​ສອບ​ຮູບ​ໜ້າ​ເຮັດ​ວຽກ​ຢູ່, ຕົວ​ແທນ​ທີ່​ເຊື່ອ​ຖື​ໄດ້​ຖືກ​ເປີດ​ໃຊ້."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ຖືກ​ຈັດ​ການ​ໂດຍ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ​ສາ​ມາດ​ເຝົ້າ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້ ຮວມ​ເຖິງ​ອີ​ເມວ, ແອັບຯ ແລະ​ເວັບ​ໄຊ​ທີ່​ເຂົ້າ​ລະ​​ຫັດ. ສຳ​ລັບ​ຂໍ້​ມູນ​ເພີ່ມ​ເຕີມ, ໃຫ້​ຕິດ​ຕໍ່​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ.\n\nອີກ​ຢ່າງ​ນຶ່ງ, ທ່ານມອບ​ສິດ​ອະ​ນຸ​ຍາດໃຫ້ \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ເພື່ອ​ຕັ້ງ​ຄ່າ​ການ​ເຊື່ອມ​ຕໍ່ VPN. ແອັບຯ​ນີ້​ສາ​ມາດ​ເຝົ້າ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ຖືກ​ຈັດ​ການ​ໂດຍ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ​ສາ​ມາດ​ເຝົ້າ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້ ຮວມ​ເຖິງ​ອີ​ເມວ, ແອັບຯ ແລະ​ເວັບ​ໄຊ​ທີ່​ເຂົ້າ​ລະ​​ຫັດ. ສຳ​ລັບ​ຂໍ້​ມູນ​ເພີ່ມ​ເຕີມ, ໃຫ້​ຕິດ​ຕໍ່​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ.\n\nນອກ​ຈາກ​ນັ້ນ, ທ່ານ​​ໄດ້​ເຊື່ອມ​ຕໍ່​ຫາ VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). ຜູ່​ໃຫ້​ບໍ​ລິ​ການ VPN ຂອງ​ທ່ານ​ສາ​ມາດ​ເຝົ້າ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້​ເຊັ່ນ​ກັນ."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"ຖືກ​ປິດ​ສຽງ​ໂດຍ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a8ee3da..e9901d7 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"atrakinti"</string>
     <string name="phone_label" msgid="2320074140205331708">"atidaryti telefoną"</string>
     <string name="camera_label" msgid="7261107956054836961">"atidaryti fotoaparatą"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Įrenginys apsaugotas."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Įrenginys neapsaugotas."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Įrenginys apsaugotas, patikima priemonė aktyvi."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Įrenginys neapsaugotas, patikima priemonė aktyvi."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Veido atpažinimo funkcija vykdoma, patikima priemonė aktyvi."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Perjungti įvesties metodo mygtuką."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Suderinamumo priartinimo mygtukas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Padidinti ekraną."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Šį įrenginį tvarko:\n„<xliff:g id="ORGANIZATION">%1$s</xliff:g>“\n\nAdministratorius gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir saugias svetaines. Kad gautumėte daugiau informacijos, susisiekite su administratoriumi.\n\nSuteikėte leidimą „<xliff:g id="APPLICATION">%2$s</xliff:g>“ užmegzti VPN ryšį. Ši programa taip pat gali stebėti tinklo veiklą."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Šį įrenginį tvarko:\n„<xliff:g id="ORGANIZATION">%1$s</xliff:g>“\n\nAdministratorius gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir saugias svetaines. Kad gautumėte daugiau informacijos, susisiekite su administratoriumi.\n\nBe to, esate prisijungę prie VPN („<xliff:g id="APPLICATION">%2$s</xliff:g>“). VPN paslaugos teikėjas taip pat gali stebėti tinklo veiklą."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Įrenginys liks užrakintas, kol neatrakinsite jo neautomatiniu būdu"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Nutildė <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 62f3147..fd38d6e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"atbloķēt"</string>
     <string name="phone_label" msgid="2320074140205331708">"atvērt tālruni"</string>
     <string name="camera_label" msgid="7261107956054836961">"atvērt kameru"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Ierīce ir aizsargāta."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Ierīce nav aizsargāta."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Ierīce ir aizsargāta, uzticamības pārbaudes programma ir aktīva."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Ierīce nav aizsargāta, uzticamības pārbaudes programma ir aktīva."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Sejas noteikšana darbojas, uzticamības pārbaudes programma ir aktīva."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ievades metodes maiņas poga."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Saderības tālummaiņas poga."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Veikt tālummaiņu no mazāka ekrāna uz lielāku."</string>
@@ -124,7 +119,7 @@
     <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi: trīs joslas"</string>
     <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Pilna piekļuve Wi-Fi signālam"</string>
     <string name="accessibility_wifi_name" msgid="7202151365171148501">"Ir izveidots savienojums ar <xliff:g id="WIFI">%s</xliff:g>."</string>
-    <string name="accessibility_bluetooth_name" msgid="8441517146585531676">"Ir izveidots savienojums ar <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
+    <string name="accessibility_bluetooth_name" msgid="8441517146585531676">"Ir izveidots savienojum ar <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Bez WiMAX."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX viena josla."</string>
     <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX divas joslas."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Šo ierīci pārvalda:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJūsu administrators var pārraudzīt tīklā veiktās darbības, arī e-pastus, lietotnes un drošās vietnes. Lai uzzinātu vairāk, sazinieties ar administratoru.\n\nJūs arī piešķīrāt atļauju izveidot savienojumu ar VPN tīklu lietotnei “<xliff:g id="APPLICATION">%2$s</xliff:g>”. Šī lietotne arī var pārraudzīt jūsu tīklā veiktās darbības."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Šo ierīci pārvalda:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nJūsu administrators var pārraudzīt jūsu tīklā veiktās darbības, arī e-pastus, lietotnes un drošās vietnes. Lai uzzinātu vairāk, sazinieties ar administratoru.\n\nIr arī izveidots savienojums ar VPN tīklu (“<xliff:g id="APPLICATION">%2$s</xliff:g>”). Tīklā veiktās darbības var pārraudzīt arī jūsu VPN pakalpojumu sniedzējs."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Ierīce būs bloķēta, līdz to manuāli atbloķēsiet."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Skaņu izslēdza <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index b8b9251..7f12ebb 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"അൺലോക്കുചെയ്യുക"</string>
     <string name="phone_label" msgid="2320074140205331708">"ഫോൺ തുറക്കുക"</string>
     <string name="camera_label" msgid="7261107956054836961">"ക്യാമറ തുറക്കുക"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"ഉപകരണം സുരക്ഷിതമാണ്."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"ഉപകരണം സുരക്ഷിതമല്ല."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"ഉപകരണം സുരക്ഷിതമാണ്, പരിചിത ഏജന്റ് സജീവമാണ്."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"ഉപകരണം സുരക്ഷിതമല്ല, പരിചിത ഏജന്റ് സജീവമാണ്."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"മുഖം കണ്ടെത്തൽ പ്രവർത്തിക്കുന്നു, പരിചിത ഏജന്റ് സജീവമാണ്."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ടൈപ്പുചെയ്യൽ രീതി ബട്ടൺ മാറുക."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ചെറുതിൽ നിന്ന് വലിയ സ്‌ക്രീനിലേക്ക് സൂം ചെയ്യുക."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"നിങ്ങളുടെ ഉപകരണം നിയന്ത്രിക്കുന്നത് ഇതാണ്:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nനിങ്ങളുടെ അഡ്‌മിനിസ്ട്രേറ്റർ ഇമെയിലുകളും അപ്ലിക്കേഷനുകളും വെബ്‌സൈറ്റുകൾ സുരക്ഷിതമാക്കലും ഉൾപ്പെടെയുള്ള നിങ്ങളുടെ നെറ്റ്‌വർക്ക് പ്രവർത്തനങ്ങൾ നിരീക്ഷിക്കുന്നതിന് പ്രാപ്‌തമാണ്. കൂടുതൽ വിവരങ്ങൾക്ക് അഡ്‌മിനിസ്ട്രേറ്ററെ ബന്ധപ്പെടുക.\n\nഅതോടൊപ്പം, നിങ്ങൾ ഒരു VPN കണക്ഷൻ സജ്ജീകരിക്കാൻ \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" എന്നതിന് അനുമതിയും നൽകി. ഈ അപ്ലിക്കേഷന് നെറ്റ്‌വർക്ക് പ്രവർത്തനവും നിരീക്ഷിക്കാനാകും."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"നിങ്ങളുടെ ഉപകരണം നിയന്ത്രിക്കുന്നത് ഇതാണ്:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nനിങ്ങളുടെ അഡ്‌മിനിസ്ട്രേറ്റർ ഇമെയിലുകളും അപ്ലിക്കേഷനുകളും വെബ്‌സൈറ്റുകൾ സുരക്ഷിതമാക്കലും ഉൾപ്പെടെയുള്ള നിങ്ങളുടെ നെറ്റ്‌വർക്ക് പ്രവർത്തനങ്ങൾ നിരീക്ഷിക്കുന്നതിന് പ്രാപ്‌തമാണ്. കൂടുതൽ വിവരങ്ങൾക്ക് അഡ്‌മിനിസ്ട്രേറ്ററെ ബന്ധപ്പെടുക.\n\nഅതോടൊപ്പം, നിങ്ങൾ ഒരു VPN-ലും (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") കണക്റ്റുചെയ്തിരിക്കുന്നു. നിങ്ങളുടെ VPN സേവന ദാതാവിന് നെറ്റ്‌വർക്ക് പ്രവർത്തനവും നിരീക്ഷിക്കാനാകും."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"നിങ്ങൾ സ്വമേധയാ അൺലോക്കുചെയ്യുന്നതുവരെ ഉപകരണം ലോക്കുചെയ്‌തതായി തുടരും"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>, മ്യൂട്ടുചെയ്‌തു"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 99701c8..0667c32 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"अनलॉक करा"</string>
     <string name="phone_label" msgid="2320074140205331708">"फोन उघडा"</string>
     <string name="camera_label" msgid="7261107956054836961">"कॅमेरा उघडा"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"डिव्‍हाइस सुरक्षित केले."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"डिव्‍हाइस सुरक्षित केले नाही."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"डिव्‍हाइस सुरक्षित केले, विश्वासू एजंट सक्रिय."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"डिव्‍हाइस सुरक्षित केले नाही, विश्वासू एजंट सक्रिय."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"चेहरा ओळख चालू आहे, विश्वासू एजंट सक्रिय."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धत स्‍विच करा बटण."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"सुसंगतता झूम बटण."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"लहानपासून मोठ्‍या स्‍क्रीनवर झूम करा."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"हे डिव्हाइस याद्वारे व्यवस्थापित केले जाते:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइट, यासह आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण VPN कनेक्शन सेट करण्यासाठी \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"हे डिव्हाइस याद्वारे व्यवस्थापित केले जाते:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइट यासह आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN शी कनेक्ट केले आहे (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"आपण व्यक्तिचलितपणे अनलॉक करेपर्यंत डिव्हाइस लॉक केलेले राहील"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारे नि:शब्द केले"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 0cf8318..02204560 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -84,22 +84,14 @@
     <string name="accessibility_search_light" msgid="1103867596330271848">"Cari"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
     <string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
-    <!-- no translation found for unlock_label (8779712358041029439) -->
-    <skip />
-    <!-- no translation found for phone_label (2320074140205331708) -->
-    <skip />
-    <!-- no translation found for camera_label (7261107956054836961) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="unlock_label" msgid="8779712358041029439">"buka kunci"</string>
+    <string name="phone_label" msgid="2320074140205331708">"buka telefon"</string>
+    <string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Peranti selamat."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Peranti tidak selamat."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Peranti selamat, ejen amanah aktif."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Peranti tidak selamat, ejen amanah aktif."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Pengecaman muka sedang berjalan, ejen amanah aktif."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butang tukar kaedah input."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butang zum keserasian."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Skrin zum lebih kecil kepada lebih besar."</string>
@@ -174,65 +166,37 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"Skrin terbaru."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_off (8716484460897819400) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_on (6440117170789528622) -->
-    <skip />
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi dimatikan."</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Wifi dihidupkan."</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mudah Alih <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateri <xliff:g id="STATE">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_airplane_off (7786329360056634412) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_on (6406141469157599296) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_off (66846307818850664) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_on (8983005603505087728) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_off (2133631372372064339) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_on (7681999166216621838) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connecting (6953242966685343855) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connected (4306637793614573659) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_off (2730003763480934529) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_on (8722351798763206577) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_off (5119080556976115520) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_on (5809937096590102036) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_off (8526845571503387376) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_on (339403053079338468) -->
-    <skip />
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Mod pesawat dimatikan."</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Mod pesawat dihidupkan."</string>
+    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Mod pesawat dimatikan."</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Mod pesawat dihidupkan."</string>
+    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Bluetooth dimatikan."</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Bluetooth dihidupkan."</string>
+    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"Bluetooth menyambung."</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth disambungkan."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"Bluetooth dimatikan."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"Bluetooth dihidupkan."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Pelaporan lokasi dimatikan."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Pelaporan lokasi dihidupkan."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"Pelaporan lokasi dimatikan."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"Pelaporan lokasi dihidupkan."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Penggera ditetapkan pada <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (3115847794692516306) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (3659274935356197708) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (2404728746293515623) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_off (4936432000069786988) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_on (2003479320007841077) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_off (3303701786768224304) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_on (6531793301533894686) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_off (4406577213290173911) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_on (6897462320184911126) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_off (5004708003447561394) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_on (2890951609226476206) -->
-    <skip />
-    <!-- no translation found for accessibility_casting_turned_off (1430668982271976172) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Tutup panel."</string>
+    <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lagi masa."</string>
+    <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kurang masa."</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampu suluh dimatikan."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampu suluh dihidupkan."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampu suluh dimatikan."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampu suluh dihidupkan."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Penyongsangan warna dimatikan."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Penyongsangan warna dihidupkan."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Tempat liputan mudah alih bergerak dimatikan."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Tempat liputan mudah alih bergerak dihidupkan."</string>
+    <string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Penghantaran skrin dihentikan."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan paparan"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data 2G-3G dimatikan"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data 4G dimatikan"</string>
@@ -250,12 +214,9 @@
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrin dikunci dalam orientasi landskap."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrin dikunci dalam orientasi potret."</string>
-    <!-- no translation found for accessibility_rotation_lock_off_changed (8134601071026305153) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_landscape_changed (3135965553707519743) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_portrait_changed (8922481981834012126) -->
-    <skip />
+    <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"Skrin kini akan berputar secara automatik."</string>
+    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"Skrin kini dikunci dalam orientasi landskap."</string>
+    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"Skrin kini dikunci dalam orientasi potret."</string>
     <string name="dessert_case" msgid="1295161776223959221">"Bekas Pencuci Mulut"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Lamun"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
@@ -376,8 +337,7 @@
     <string name="vpn_footer" msgid="2388611096129106812">"Rangkaian mungkin dipantau"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"Pemantauan peranti"</string>
     <string name="monitoring_title" msgid="169206259253048106">"Pemantauan rangkaian"</string>
-    <!-- no translation found for disable_vpn (4435534311510272506) -->
-    <skip />
+    <string name="disable_vpn" msgid="4435534311510272506">"Lumpuhkan VPN"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"Putuskan sambungan VPN"</string>
     <string name="monitoring_description_device_owned" msgid="7512371572956715493">"Peranti ini diurus oleh:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nPentadbir anda boleh mengawasi aktiviti peranti dan rangkaian anda, termasuk e-mel, apl dan tapak web selamat.\n\nUntuk maklumat lanjut, hubungi pentadbir anda."</string>
     <string name="monitoring_description_vpn" msgid="7288268682714305659">"Anda memberi \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" kebenaran untuk menyediakan sambungan VPN.\n\nApl ini boleh memantau aktiviti peranti dan rangkaian anda, termasuk e-mel, apl dan tapak web yang selamat."</string>
@@ -385,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Peranti ini diuruskan oleh:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nPentadbir anda berkemampuan memantau aktiviti rangkaian anda termasuk e-mel, apl dan tapak web yang selamat. Untuk maklumat lanjut, hubungi pentadbir anda.\n\nAnda juga memberikan \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" kebenaran untuk menyediakan rangkaian VPN. Apl ini juga boleh memantau aktiviti rangkaian."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Peranti ini diuruskan oleh:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nPentadbir anda berkemampuan memantau aktiviti rangkaian anda termasuk e-mel, apl dan tapak web yang selamat. Untuk maklumat lanjut, hubungi pentadbir anda.\n\nAnda juga disambungkan ke VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Pembekal perkhidmatan VPN anda juga boleh memantau aktiviti rangkaian."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Peranti akan kekal terkunci sehingga anda membuka kunci secara manual"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Diredam oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 513f909..301b7a5 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -85,16 +85,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"သော့ဖွင့်ရန်"</string>
     <string name="phone_label" msgid="2320074140205331708">"ဖုန်းကို ဖွင့်ရန်"</string>
     <string name="camera_label" msgid="7261107956054836961">"ကင်မရာ ဖွင့်ရန်"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"စက် လုံခြုံသည်။"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"စက် မလုံခြုံပါ။"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"စက် လုံခြုံပြီး၊ ယုံကြည်မှု အေးဂျင့် အလုပ်လုပ်သည်။"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"စက် မလုံခြုံပါ၊ ယုံကြည်မှု အေးဂျင့် အလုပ်လုပ်သည်။"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"မျက်နှာ စိစစ်မှု စတင်ပြီး၊ ယုံကြည်မှု အေးဂျင့် အလုပ်လုပ်သည်။"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ထည့်သွင်းခြင်းခလုတ်အား ပြောင်းခြင်း"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"အံ့ဝင်သောချုံ့ချဲ့ခလုတ်"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ဖန်သားပြင်ပေါ်တွင် အသေးမှအကြီးသို့ချဲ့ခြင်း"</string>
@@ -346,6 +341,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ဒီကိရိယာကို စီမံကွပ်ကဲသူမှာ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nသင်၏ စီမံအုပ်ချုပ်သူက သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို၊ အီးမေးလ်များ၊ appများ နှင့် လုံခြုံသည့် ဝက်ဘ်ဆိုက်များ အပါအဝင်ကို၊ စောင့်ကြပ် နိုင်ပါသည်။ အချက်အလက်များ ပိုပြီး ရယူရန်၊ သင်၏ စီမံအုပ်ချုပ်သူကို ဆက်သွယ်ပါ။\n\n ထို့အပြင် သင်သည် \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" အား VPN ချိတ်ဆက်မှု စဖွင့်လုပ်ကိုင်ရန် ခွင့်ပြုခဲ့သည်။ ဒီ  appကပါ သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို စောင့်ကြပ် နိုင်ပါသည်။"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ဒီကိရိယာကို စီမံကွပ်ကဲသူမှာ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nသင်၏  စီမံအုပ်ချုပ်သူက သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို၊ အီးမေးလ်များ၊ appများ နှင့် လုံခြုံသည့် ဝက်ဘ်ဆိုက်များ အပါအဝင်ကို၊ စောင့်ကြပ် နိုင်ပါသည်။ အချက်အလက်များ ပိုပြီး ရယူရန်၊ သင်၏ စီမံအုပ်ချုပ်သူကို ဆက်သွယ်ပါ။\n\nထို့အပြင်၊ သင်သည် VPN  (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") သို့ ချိတ်ဆက်ထားသည်။ သင်၏ VPN ဝန်ဆောင်မှုကို စီမံပေးသူကပါ ကွန်ရက် လှုပ်ရှားမှုများကို စောင့်ကြပ်နိုင်သေးသည်။"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"သင်က လက်ဖြင့် သော့မဖွင့်မချင်း ကိရိယာမှာ သော့ပိတ်လျက် ရှိနေမည်"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> အသံပိတ်သည်"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 212bcfb..e10fde7 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"lås opp"</string>
     <string name="phone_label" msgid="2320074140205331708">"åpne telefonen"</string>
     <string name="camera_label" msgid="7261107956054836961">"åpne kamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Enheten er sikker."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Enheten er ikke sikker."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Enheten er sikker – pålitelig agent er aktiv."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Enheten er ikke sikker – pålitelig agent er aktiv."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Ansiktsgjenkjennelse kjører – pålitelig agent er aktiv."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bytt knapp for inndatametode."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoomknapp for kompatibilitet."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom fra mindre til større skjerm."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Denne enheten administreres av:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratoren din kan overvåke nettverksaktiviteten din, inkludert e-poster, apper og sikre nettsteder. Ta kontakt med administratoren din for mer om dette.\n\nI tillegg ga du «<xliff:g id="APPLICATION">%2$s</xliff:g>» tillatelse til å konfigurere en VPN-tilkobling. Denne appen kan også overvåke nettverksaktiviteten din."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Denne enheten administreres av:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratoren din kan overvåke nettverksaktiviteten din, inkludert e-poster, apper og sikre nettsteder. Ta kontakt med administratoren din for mer om dette.\n\nI tillegg er enheten koblet til et VPN-nettverk («<xliff:g id="APPLICATION">%2$s</xliff:g>»). VPN-tjenesteleverandøren kan også overvåke nettverksaktiviteten din."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten forblir låst til du låser den opp manuelt"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> har kuttet lyden"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 1e6414b..5a87938 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ontgrendelen"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefoon openen"</string>
     <string name="camera_label" msgid="7261107956054836961">"camera openen"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Apparaat is beveiligd."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Apparaat is niet beveiligd."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Apparaat is beveiligd, trust agent is actief."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Apparaat is niet beveiligd, trust agent is actief."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Gezichtsherkenning wordt uitgevoerd, trust agent is actief."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knop voor wijzigen invoermethode."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knop voor compatibiliteitszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kleiner scherm uitzoomen naar groter scherm."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Dit apparaat wordt beheerd door:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nUw beheerder kan uw netwerkactiviteit beheren, waaronder e-mails, apps en beveiligde websites. Neem voor meer informatie contact op met uw beheerder.\n\nDaarnaast heeft u \'<xliff:g id="APPLICATION">%2$s</xliff:g>\' toestemming gegeven een VPN-verbinding in te stellen. Deze app kan uw netwerkactiviteit ook controleren."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Dit apparaat wordt beheerd door:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nUw beheerder kan uw netwerkactiviteit beheren, waaronder e-mails, apps en beveiligde websites. Neem voor meer informatie contact op met uw beheerder.\n\nDaarnaast bent u verbonden met een VPN (\'<xliff:g id="APPLICATION">%2$s</xliff:g>\'). Uw VPN-serviceprovider kan uw netwerkactiviteit ook controleren."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Het apparaat blijft vergrendeld totdat u het handmatig ontgrendelt"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Gedempt door <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b167a39..28368ea 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"odblokuj"</string>
     <string name="phone_label" msgid="2320074140205331708">"otwórz telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"otwórz aparat"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Urządzenie jest zabezpieczone."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Urządzenie nie jest zabezpieczone."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Urządzenie jest zabezpieczone. Agent zaufania jest aktywny."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Urządzenie nie jest zabezpieczone. Agent zaufania jest aktywny."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Wykrywanie twarzy jest włączone. Agent zaufania jest aktywny."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Przycisk przełączania metody wprowadzania."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Przycisk powiększenia na potrzeby zgodności."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Powiększa mniejszy ekran do większego."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Urządzeniem zarządza:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministrator ma możliwość monitorowania Twojej aktywności w sieci, w tym e-maili, aplikacji i bezpiecznych witryn. Skontaktuj się z nim, by dowiedzieć się więcej.\n\nDałeś też aplikacji „<xliff:g id="APPLICATION">%2$s</xliff:g>” uprawnienia do skonfigurowania połączenia VPN. Ona również może monitorować aktywność sieciową."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Urządzeniem zarządza:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministrator ma możliwość monitorowania Twojej aktywności w sieci, w tym e-maili, aplikacji i bezpiecznych witryn. Skontaktuj się z nim, by dowiedzieć się więcej.\n\nŁączysz się też z siecią VPN („<xliff:g id="APPLICATION">%2$s</xliff:g>”). Dostawca usługi VPN również może monitorować aktywność sieciową."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Urządzenie pozostanie zablokowane, aż odblokujesz je ręcznie"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Ściszone przez: <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d98ef17..a9ad1c8 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir telemóvel"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir câmara"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Dispositivo protegido."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Dispositivo não protegido."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Dispositivo protegido, agente fidedigno ativo."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Dispositivo não protegido, agente fidedigno ativo."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Deteção de rosto em execução, agente fidedigno ativo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alternar botão de método de introdução."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão zoom de compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom menor para ecrã maior."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Este dispositivo é gerido por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\no admin. pode monitorizar a atividade da rede, incluindo emails, aplicações e Websites seguros. Para mais informações, contacte o administrador.\n\nAlém disso, deu permissão a \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" para configurar uma ligação VPN. Esta aplicação pode também monitorizar a atividade da rede."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Este dispositivo é gerido por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\no administrador pode monitorizar a atividade da rede, incluindo emails, aplicações e Websites seguros. Para mais informações, contacte o administrador.\n\nAlém disso, está ligado a uma VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). O fornecedor de serviços VPN pode também monitorizar a atividade da rede."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até ser desbloqueado manualmente"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Som desativado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 81565c3..0b22039 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir smartphone"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Dispositivo protegido."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Dispositivo não protegido."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Dispositivo protegido, agente de confiança ativo."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Dispositivo não protegido, agente de confiança ativo."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Reconhecimento facial em execução, agente de confiança ativo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Este dispositivo é gerenciado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nO administrador pode monitorar sua atividade na rede, incluindo e-mails, apps e websites seguros. Para mais informações, entre em contato com o administrador.\n\nAlém disso, você autorizou \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" a configurar uma conexão VPN. Esse app também pode monitorar a atividade na rede."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Este dispositivo é gerenciado por:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nO administrador pode monitorar sua atividade na rede, incluindo e-mails, apps e websites seguros. Para mais informações, entre em contato com o administrador.\n\nAlém disso, você está conectado a uma VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). O provedor de serviços de VPN também pode monitorar a atividade na rede."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Som desativado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index aa6fa592..a911586 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"deblocați"</string>
     <string name="phone_label" msgid="2320074140205331708">"deschideți telefonul"</string>
     <string name="camera_label" msgid="7261107956054836961">"deschideți camera foto"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Dispozitivul este securizat."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Dispozitivul nu este securizat."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Dispozitivul este securizat. Agentul de încredere este activ."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Dispozitivul nu este securizat. Agentul de încredere este activ."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Se execută detectarea feței. Agentul de încredere este activ."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Buton pentru comutarea metodei de introducere."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceţi zoom de la o imagine mai mică la una mai mare."</string>
@@ -351,6 +346,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Dispozitiv administrat de:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratorul vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile securizate. Pentru detalii, contactați administratorul.\n\nAți permis aplicației „<xliff:g id="APPLICATION">%2$s</xliff:g>” să configureze o conexiune VPN. Aplicația vă poate monitoriza activitatea în rețea."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Dispozitiv administrat de:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratorul vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile securizate. Pentru detalii, contactați administratorul.\n\nSunteți conectat(ă) la o rețea VPN („<xliff:g id="APPLICATION">%2$s</xliff:g>”). Furnizorul de servicii VPN vă poate monitoriza activitatea în rețea."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Dispozitivul va rămâne blocat până când îl deblocați manual"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Dezactivate de <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0cc88f3..354da5ac 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"Разблокировать."</string>
     <string name="phone_label" msgid="2320074140205331708">"Открыть телефон."</string>
     <string name="camera_label" msgid="7261107956054836961">"Открыть камеру."</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Устройство защищено."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Устройство не защищено."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Устройство защищено, промежуточный агент активирован."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Устройство не защищено, промежуточный агент активирован."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Распознавание лица включено, промежуточный агент активирован."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабирования (режим совместимости)"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Уменьшение изображения для увеличения свободного места на экране."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Этим устройством управляет организация:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдминистратор может отслеживать вашу работу с электронной почтой, приложениями и защищенными веб-сайтами. Обратитесь к нему за дополнительной информацией.\n\nВаши действия в сети также доступны приложению \"<xliff:g id="APPLICATION">%2$s</xliff:g>\", которому вы разрешили подключаться к сети VPN."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Этим устройством управляет организация:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдминистратор может отслеживать вашу работу с электронной почтой, приложениями и защищенными веб-сайтами. Обратитесь к нему за дополнительной информацией.\n\nУстройство подключено к сети VPN (<xliff:g id="APPLICATION">%2$s</xliff:g>). Ваши действия также доступны поставщику услуг VPN."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройство необходимо будет разблокировать вручную"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Звук отключен приложением \"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>\""</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index b12ee5a..8b8dbd4 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -84,12 +84,9 @@
     <string name="accessibility_search_light" msgid="1103867596330271848">"සොයන්න"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"කැමරාව"</string>
     <string name="accessibility_phone_button" msgid="6738112589538563574">"දුරකථනය"</string>
-    <!-- no translation found for unlock_label (8779712358041029439) -->
-    <skip />
-    <!-- no translation found for phone_label (2320074140205331708) -->
-    <skip />
-    <!-- no translation found for camera_label (7261107956054836961) -->
-    <skip />
+    <string name="unlock_label" msgid="8779712358041029439">"අඟුල අරින්න"</string>
+    <string name="phone_label" msgid="2320074140205331708">"දුරකථනය විවෘත කරන්න"</string>
+    <string name="camera_label" msgid="7261107956054836961">"කැමරාව විවෘත කරන්න"</string>
     <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
     <skip />
     <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
@@ -174,65 +171,37 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"මෑතක තිර."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"පරිශීලකයා <xliff:g id="USER">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_off (8716484460897819400) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_on (6440117170789528622) -->
-    <skip />
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Wifi සක්‍රියයි."</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"ජංගම <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"බැටරිය <xliff:g id="STATE">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_airplane_off (7786329360056634412) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_on (6406141469157599296) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_off (66846307818850664) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_on (8983005603505087728) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_off (2133631372372064339) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_on (7681999166216621838) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connecting (6953242966685343855) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connected (4306637793614573659) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_off (2730003763480934529) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_on (8722351798763206577) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_off (5119080556976115520) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_on (5809937096590102036) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_off (8526845571503387376) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_on (339403053079338468) -->
-    <skip />
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"අහස්යානා අකාරය අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"අහස්යානා ආකාරය සක්‍රීයයි."</string>
+    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"අහස්යානා අකාරය අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"අහස්යානා ආකාරය සක්‍රීයයි."</string>
+    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"බ්ලූටූත් අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"බ්ලූටූත් සක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"බ්ලූටූත් සම්බන්ධවෙමින්."</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"බ්ලූටූත් සම්බන්ධිතයි."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"බ්ලූටූත් අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"බ්ලූටූත් සක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"ස්ථානය වාර්තාකරණය අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"ස්ථානය වාර්තාකරණය සක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"ස්ථානය වාර්තාකරණය අක්‍රියයි."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"ස්ථානය වාර්තාකරණය සක්‍රියයි."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"<xliff:g id="TIME">%s</xliff:g> සඳහා සීනුව සකස් කර ඇත."</string>
-    <!-- no translation found for accessibility_quick_settings_close (3115847794692516306) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (3659274935356197708) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (2404728746293515623) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_off (4936432000069786988) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_on (2003479320007841077) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_off (3303701786768224304) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_on (6531793301533894686) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_off (4406577213290173911) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_on (6897462320184911126) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_off (5004708003447561394) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_on (2890951609226476206) -->
-    <skip />
-    <!-- no translation found for accessibility_casting_turned_off (1430668982271976172) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"පැනලය වහන්න."</string>
+    <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"වේලාව වැඩියෙන්."</string>
+    <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"වේලාව අඩුවෙන්."</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"සැණෙළි ආලෝකය අක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"සැණෙළි ආලෝකය සක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"සැණෙළි ආලෝකය අක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"සැණෙළි ආලෝකය සක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"වර්ණ අපවර්තනය අක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"වර්ණ අපවර්තනය සක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"ජංගම හොට්ස්පොටය අක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"ජංගම හොට්ස්පොටය සක්‍රිය කරන ලදි."</string>
+    <string name="accessibility_casting_turned_off" msgid="1430668982271976172">"තිරය විකාශය කිරීම නැවත් වන ලදි."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"දීප්තිය දර්ශනය කරන්න"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G දත්ත අක්‍රියයි"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G දත්ත අක්‍රියයි"</string>
@@ -250,12 +219,9 @@
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"තිරය ස්වයංක්‍රීයව කරකැවේ."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"තිරය තිරස් දිශානතියෙහි අගුළු දමා ඇත."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"තිරය සිරස් දිශානතිය තුළ අගුළු වැටී ඇත."</string>
-    <!-- no translation found for accessibility_rotation_lock_off_changed (8134601071026305153) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_landscape_changed (3135965553707519743) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_portrait_changed (8922481981834012126) -->
-    <skip />
+    <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"තිරය ස්වයංක්‍රීයව කරකැවේ."</string>
+    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"තිරය දැන් තිරස් දිශානතිය අගුළු දමා ඇත."</string>
+    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"තිරය සිරස් දිශානතිය තුළ අගුළු වැටී ඇත."</string>
     <string name="dessert_case" msgid="1295161776223959221">"අතුරුපස අවස්තාව"</string>
     <string name="start_dreams" msgid="7219575858348719790">"දවල් හීනය"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ඊතර නෙට්"</string>
@@ -376,8 +342,7 @@
     <string name="vpn_footer" msgid="2388611096129106812">"ඇතැම් විට ජාලය නිරීක්ෂණය විය හැක"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"උපාංගය නිරීක්ෂණය"</string>
     <string name="monitoring_title" msgid="169206259253048106">"ජාල නිරීක්ෂණය"</string>
-    <!-- no translation found for disable_vpn (4435534311510272506) -->
-    <skip />
+    <string name="disable_vpn" msgid="4435534311510272506">"VPN අබල කරන්න."</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN විසන්ධි කරන්න"</string>
     <string name="monitoring_description_device_owned" msgid="7512371572956715493">"මෙම උපාංගය කළමනාකරණය කරනු ලබන්නේ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nඊ-මේල්, යෙදුම්, සහ ආරක්ෂාකාරී වෙබ් අඩවි ඇතුළු, ඔබගේ ජාල ක්‍රියාකාරකම නිරීක්ෂණය කිරීමට ඔබගේ පරිපාලකට හැක.\n\nවැඩිදුර විස්තර සඳහා, ඔබගේ පරිපාලක අමතන්න."</string>
     <string name="monitoring_description_vpn" msgid="7288268682714305659">"VPN සම්බන්ධතාව සකස් කරගැනීමට \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" අවසර ඔබ දෙන ලදි.\n\nඊ-තැපැල්, යෙදුම්, සහ අරක්ෂිත වෙබ් අඩවි ඇතුළුව ඔබගේ ජාලයේ ක්‍රියාකාරකම් නිරීක්ෂණය කිරීමට මෙම යෙදුමට හැකිය."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f26c9e4..86222bc 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"odomknúť"</string>
     <string name="phone_label" msgid="2320074140205331708">"otvoriť telefón"</string>
     <string name="camera_label" msgid="7261107956054836961">"spustiť fotoaparát"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Zariadenie je zabezpečené."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Zariadenie nie je zabezpečené."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Zariadenie je zabezpečené, funkcia agent dôvery je aktívna."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Zariadenie nie je zabezpečené, funkcia agent dôvery je aktívna."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Prebieha rozpoznávanie tváre, funkcia agent dôvery je aktívna."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačidlo prepnutia metódy vstupu."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zväčšiť menší obrázok na väčšiu obrazovku."</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Toto zariadenie spravuje organizácia:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nSprávca môže sledovať vašu aktivitu v sieti vrátane e-mailov, aplikácií a zabezpečených webových stránok. Ďalšie informácie získate od svojho správcu.\n\nZároveň ste aplikácii <xliff:g id="APPLICATION">%2$s</xliff:g> povolili nastaviť pripojenie VPN. Táto aplikácia môže tiež sledovať vašu aktivitu v sieti."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Toto zariadenie spravuje organizácia:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nSprávca môže sledovať vašu aktivitu v sieti vrátane e-mailov, aplikácií a zabezpečených webových stránok. Ďalšie informácie získate od svojho správcu.\n\nZároveň ste pripojený/-á aj k sieti VPN (<xliff:g id="APPLICATION">%2$s</xliff:g>). Poskytovateľ služby VPN môže tiež sledovať vašu aktivitu v sieti."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Zariadenie zostane uzamknuté, dokým ho ručne neodomknete."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Stlmené aplikáciou <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 733f9b3..bf0162c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"odkleni"</string>
     <string name="phone_label" msgid="2320074140205331708">"odpri telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"odpri fotoaparat"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Naprava zavarovana."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Naprava ni zavarovana."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Naprava zavarovana, posrednik zaupanja aktiven."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Naprava ni zavarovana, posrednik zaupanja aktiven."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Prepoznavanje obraza vklopljeno, posrednik zaupanja aktiven."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za preklop načina vnosa."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb povečave za združljivost."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Povečava manjšega na večji zaslon."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"To napravo upravlja:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nSkrbnik lahko nadzira vašo dejavnost v omrežju, vključno z e-pošto, aplikacijami in varnimi spletnimi mesti. Če želite več informacij, se obrnite na skrbnika.\n\nPoleg tega ste aplikaciji »<xliff:g id="APPLICATION">%2$s</xliff:g>« dovolili vzpostavitev povezave z omrežjem VPN. Vašo dejavnost v omrežju lahko nadzoruje tudi ta aplikacija."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"To napravo upravlja:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nSkrbnik lahko nadzira vašo dejavnost v omrežju, vključno z e-pošto, aplikacijami in varnimi spletnimi mesti. Če želite več informacij, se obrnite na skrbnika.\n\nPoleg tega ste povezani v omrežje VPN (»<xliff:g id="APPLICATION">%2$s</xliff:g>«). Vašo dejavnost v omrežju lahko nadzira tudi ponudnik omrežja VPN."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Naprava bo ostala zaklenjena, dokler je ročno ne odklenete."</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Izklop zvoka: <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8ed4490..780bb42 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"откључај"</string>
     <string name="phone_label" msgid="2320074140205331708">"отвори телефон"</string>
     <string name="camera_label" msgid="7261107956054836961">"отвори камеру"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Уређај је заштићен."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Уређај није заштићен."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Уређај је заштићен, поуздани агент је активан."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Уређај није заштићен, поуздани агент је активан."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Покренуто је препознавање лица, поуздани агент је активан."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Дугме Промени метод уноса."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Дугме Зум компатибилности."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумирање са мањег на већи екран."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Овим уређајем управља:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдминистратор може да надгледа мрежне активности, укључујући имејлове, апликације и безбедне веб-сајтове. Више информација потражите од администратора.\n\nДали сте и дозволу апликацији <xliff:g id="APPLICATION">%2$s</xliff:g> да подешава VPN везу. И та апликација може да надгледа мрежне активности."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Овим уређајем управља:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдминистратор може да надгледа мрежне активности, укључујући имејлове, апликације и безбедне веб-сајтове. Више информација потражите од администратора.\n\nПовезани сте и са VPN-ом („<xliff:g id="APPLICATION">%2$s</xliff:g>“). И добављач VPN услуге може да надгледа мрежне активности."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Уређај ће остати закључан док га не откључате ручно"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Звук је искључио/ла <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 47902fe..5494edc 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"lås upp"</string>
     <string name="phone_label" msgid="2320074140205331708">"öppna mobilen"</string>
     <string name="camera_label" msgid="7261107956054836961">"öppna kameran"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Enheten är skyddad."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Enheten är inte skyddad."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Enheten är skyddad, den betrodda agenten är aktiv."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Enheten är inte skyddad, den betrodda agenten är aktiv."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Ansiktsigenkänning körs, den betrodda agenten är aktiv."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knapp för byte av inmatningsmetod."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knapp för kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zooma mindre skärm till större."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Den här enheten administreras av:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nDin administratör kan övervaka din nätverksaktivitet, inklusive e-post, appar och säkra webbplatser. Kontakta din administratör för mer information.\n\nDu har också gett <xliff:g id="APPLICATION">%2$s</xliff:g> tillåtelse att skapa en VPN-anslutning. Även den här appen kan övervaka nätverksaktivitet."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Den här enheten administreras av:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nDin administratör kan övervaka din nätverksaktivitet, inklusive e-post, appar och säkra webbplatser. Kontakta din administratör för mer information.\n\nDu är även ansluten till VPN (<xliff:g id="APPLICATION">%2$s</xliff:g>). Även din VPN-tjänsteleverantör kan övervaka nätverksaktiviteten."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten förblir låst tills du låser upp den manuellt"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> har stängt av ljudet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 18f5fb2..3f44b63 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -85,16 +85,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"fungua"</string>
     <string name="phone_label" msgid="2320074140205331708">"fungua simu"</string>
     <string name="camera_label" msgid="7261107956054836961">"fungua kamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Kifaa kimewekewa ulinzi."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Kifaa hakijawekewa ulinzi."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Kifaa kimewekewa ulinzi, kipengele cha kutathmini hali ya kuaminika kimewashwa."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Kifaa hakijawekewa ulinzi, kipengele cha kutathmini hali ya kuaminika kimewashwa."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Utambuzi wa uso unaendeshwa, kipengele cha kutathmini hali ya kuaminika kimewashwa."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Swichi kitufe cha mbinu ingizi."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kichupo cha kukuza kwa utangamanifu"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kuza kidogo kwa skrini kubwa."</string>
@@ -197,8 +192,8 @@
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Tochi imewashwa."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Ugeuzaji rangi umezimwa."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Ugeuzaji rangi umewashwa."</string>
-    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Mtandao-hewa wa simu ya mkononi umezimwa."</string>
-    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mtandao-hewa wa simu ya mkononi umewashwa."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Mtandao-hewa unaoweza kuhamishika umezimwa."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mtandao-hewa unaoweza kuhamishika umewashwa."</string>
     <string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Utumaji wa skrini umesitishwa."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ung\'aavu wa skrini"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data ya 2G-3G imezimwa"</string>
@@ -271,7 +266,7 @@
     <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Data ya simu ya mkononi"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Matumizi ya data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data iliyosalia"</string>
-    <string name="quick_settings_cellular_detail_over_limit" msgid="3242930457130971204">"Kikomo kimefikiwa - matumizi ya data yamesitishwa"</string>
+    <string name="quick_settings_cellular_detail_over_limit" msgid="3242930457130971204">"Kikomo kimefikiwa – matumizi ya data yamesitishwa"</string>
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> imetumika"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"kikomo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
@@ -311,7 +306,7 @@
     <string name="guest_nickname" msgid="8059989128963789678">"Aliyealikwa"</string>
     <string name="guest_new_guest" msgid="600537543078847803">"Ongeza aliyealikwa"</string>
     <string name="guest_exit_guest" msgid="7187359342030096885">"Ondoa aliyealikwa"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="8480693520521766688">"Ungependa kumuondoa aliyealikwa?"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="8480693520521766688">"Ungependa kumwondoa aliyealikwa?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Programu zote na data katika kipindi hiki zitafutwa."</string>
     <string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"Ondoa"</string>
     <string name="guest_wipe_session_title" msgid="6419439912885956132">"Karibu tena, mwalikwa!"</string>
@@ -348,6 +343,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao wako."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Kifaa kitaendelea kuwa katika hali ya kufungwa hadi utakapokifungua mwenyewe"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Sauti imezimwa na <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 3cd5f67..dd158c2 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -58,6 +58,9 @@
     <!-- Size of fading edge for scrolling -->
     <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
 
+    <!-- The radius of the rounded corners on a task view. -->
+    <dimen name="recents_task_view_rounded_corners_radius">3dp</dimen>
+
     <!-- Where to place the app icon over the thumbnail -->
     <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
     <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 725b3ce..7762f34 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"திற"</string>
     <string name="phone_label" msgid="2320074140205331708">"ஃபோனைத் திற"</string>
     <string name="camera_label" msgid="7261107956054836961">"கேமராவைத் திற"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"சாதனம் பாதுகாப்பாக உள்ளது."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"சாதனம் பாதுகாப்பாக இல்லை."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"சாதனம் பாதுகாப்பாக உள்ளது, நம்பகமான ஏஜென்ட் இயக்கத்தில் உள்ளது."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"சாதனம் பாதுகாப்பாக இல்லை, நம்பகமான ஏஜென்ட் இயக்கத்தில் உள்ளது."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"முகம் கண்டறிதல் இயங்குகிறது, நம்பகமான ஏஜென்ட் இயக்கத்தில் உள்ளது."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"உள்ளீட்டு முறையை மாற்றும் பொத்தான்."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"பொருந்துமாறு அளவை மாற்றும் பொத்தான்."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"சிறியதிலிருந்து பெரிய திரைக்கு அளவை மாற்றும்."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"சாதனத்தை நிர்வகிப்பது:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nமின்னஞ்சல்கள், பயன்பாடுகள் மற்றும் பாதுகாப்பான இணையதளங்கள் உட்பட நெட்வொர்க் செயல்பாட்டை உங்கள் நிர்வாகியால் கண்காணிக்க முடியும். மேலும் தகவலுக்கு உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்.\n\nமேலும் VPN இணைப்பை அமைக்க, \"<xliff:g id="APPLICATION">%2$s</xliff:g>\"க்கு அனுமதி வழங்கியுள்ளீர்கள். இந்தப் பயன்பாட்டினால் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"சாதனத்தை நிர்வகிப்பது:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nமின்னஞ்சல்கள், பயன்பாடுகள் மற்றும் பாதுகாப்பான இணையதளங்கள் உட்பட நெட்வொர்க் செயல்பாட்டை உங்கள் நிர்வாகியால் கண்காணிக்க முடியும். மேலும் தகவலுக்கு உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்.\n\nமேலும் (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") உடன் இணைக்கப்பட்டீர்கள். VPN சேவை வழங்குநரும் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"நீங்கள் கைமுறையாகத் திறக்கும் வரை, சாதனம் பூட்டப்பட்டிருக்கும்"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ஒலியடக்கினார்"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index cae222c..0ce5e6a 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"అన్‌లాక్ చేయి"</string>
     <string name="phone_label" msgid="2320074140205331708">"ఫోన్‌ను తెరువు"</string>
     <string name="camera_label" msgid="7261107956054836961">"కెమెరాను తెరువు"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"పరికరం సురక్షితంగా ఉంది."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"పరికరం సురక్షితంగా లేదు."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"పరికరం సురక్షితంగా ఉంది, విశ్వసనీయ ఏజెంట్ సక్రియంగా ఉంది."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"పరికరం సురక్షితంగా లేదు, విశ్వసనీయ ఏజెంట్ సక్రియంగా ఉంది."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"ముఖం గుర్తింపు అమలవుతోంది, విశ్వసనీయ ఏజెంట్ సక్రియంగా ఉంది."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ఇన్‌పుట్ పద్ధతి మార్చే బటన్."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"అనుకూలత జూమ్ బటన్."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"చిన్న స్క్రీన్ నుండి పెద్దదానికి జూమ్ చేయండి."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ఈ పరికరం దీని నిర్వహణలో ఉంది:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nమీ నిర్వాహకుడు ఇమెయిల్‌లు, అనువర్తనాలు మరియు సురక్షిత వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలరు. మరింత సమాచారం కోసం, మీ నిర్వాహకుడిని సంప్రదించండి.\n\nఅలాగే, మీరు VPN కనెక్షన్‌ను సెటప్ చేయడానికి \"<xliff:g id="APPLICATION">%2$s</xliff:g>\"ని అనుమతించారు. కనుక ఈ అనువర్తనం కూడా నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ఈ పరికరం దీని నిర్వహణలో ఉంది:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nమీ నిర్వాహకుడు ఇమెయిల్‌లు, అనువర్తనాలు మరియు సురక్షిత వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలరు. మరింత సమాచారం కోసం, మీ నిర్వాహకుడిని సంప్రదించండి.\n\nఅలాగే, మీరు VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\")కి కనెక్ట్ చేయబడ్డారు. కనుక మీ VPN సేవా ప్రదాత కూడా నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలరు."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"మీరు మాన్యువల్‌గా అన్‌లాక్ చేస్తే మినహా పరికరం లాక్ చేయబడి ఉంటుంది"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ద్వారా మ్యూట్ చేయబడింది"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8399e39..cba6fd6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"ปลดล็อก"</string>
     <string name="phone_label" msgid="2320074140205331708">"เปิดโทรศัพท์"</string>
     <string name="camera_label" msgid="7261107956054836961">"เปิดกล้อง"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"อุปกรณ์ปลอดภัยแล้ว"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"อุปกรณ์ไม่มีการรักษาความปลอดภัย"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"อุปกรณ์ปลอดภัยแล้ว ใช้งานเอเจนต์ความน่าเชื่อถืออยู่"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"อุปกรณ์ไม่มีการรักษาความปลอดภัย ใช้งานเอเจนต์ความน่าเชื่อถืออยู่"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"กำลังตรวจจับใบหน้า ใช้งานเอเจนต์ความน่าเชื่อถืออยู่"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ปุ่มสลับวิธีการป้อนข้อมูล"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ปุ่มซูมที่ใช้งานร่วมกันได้"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ซูมหน้าจอให้มีขนาดใหญ่ขึ้น"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"อุปกรณ์นี้ได้รับการจัดการโดย:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nผู้ดูแลระบบของคุณสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณได้ รวมถึงอีเมล แอป และเว็บไซต์ที่ปลอดภัย สำหรับข้อมูลเพิ่มเติม โปรดติดต่อผู้ดูแลระบบของคุณ\n\nนอกจากนี้ คุณได้ให้สิทธิ์ \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" เพื่อตั้งค่าการเชื่อมต่อ VPN แอปนี้สามารถตรวจสอบกิจกรรมในเครือข่ายได้เช่นกัน"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"อุปกรณ์นี้ได้รับการจัดการโดย:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nผู้ดูแลระบบของคุณสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณได้ รวมถึงอีเมล แอป และเว็บไซต์ที่ปลอดภัย สำหรับข้อมูลเพิ่มเติม โปรดติดต่อผู้ดูแลระบบของคุณ\n\nนอกจากนี้ คุณเชื่อมต่อกับ VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") ผู้ให้บริการ VPN ของคุณสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณได้เช่นกัน"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"อุปกรณ์จะล็อกจนกว่าคุณจะปลดล็อกด้วยตนเอง"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"ปิดเสียงโดย <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 71e4400..696c227 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"i-unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"buksan ang telepono"</string>
     <string name="camera_label" msgid="7261107956054836961">"buksan ang camera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Naka-secure ang device."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Hindi naka-secure ang device."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Hindi naka-secure ang device, aktibo ang trust agent."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Hind naka-secure ang device, aktibo ang trust agent."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Gumagana ang face detection, aktibo ang trust agent."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ilipat ang button na pamamaraan ng pag-input."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Button ng zoom ng pagiging tugma."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Mag-zoom nang mas maliit sa mas malaking screen."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Ang device ay pinapamahalaan ng:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMay kakayahan ang iyong administrator na subaybayan ang iyong aktibidad sa network kabilang ang mga email, apps at secure na website. Para sa higit pang impormasyon, makipag-ugnayan sa iyong administrator.\n\nGayundin, pinahintulutan mo ang \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" na mag-set up ng koneksyon sa VPN. Maaari ding subaybayan ng app na ito ang aktibidad sa network."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Ang device ay pinapamahalaan ng:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMay kakayahan ang iyong administrator na subaybayan ang iyong aktibidad sa network kabilang ang mga email, apps at secure na website. Para sa higit pang impormasyon, makipag-ugnayan sa iyong administrator.\n\nGayundin, nakakonekta ka sa isang VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Maaari ding subaybayan ng iyong VPN service provider ang mga aktibidad sa network."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Mananatiling naka-lock ang device hanggang sa manu-mano mong i-unlock"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Na-mute ng <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8130c88..1e10f29 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"розблокувати"</string>
     <string name="phone_label" msgid="2320074140205331708">"відкрити телефон"</string>
     <string name="camera_label" msgid="7261107956054836961">"відкрити камеру"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Пристрій захищено."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Пристрій не захищено."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Пристрій захищено, довірчий агент активний."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Пристрій не захищено, довірчий агент активний."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Запущено функцію розпізнавання обличчя, довірчий агент активний."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка перемикання методу введення."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабування сумісності."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Збільшення екрана."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Цим пристроєм керує \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдміністратор може відстежувати ваші дії в мережі, зокрема листування, роботу в додатках і на захищених веб-сайтах. Щоб дізнатися більше, зверніться до адміністратора.\n\nВи також дозволили додатку <xliff:g id="APPLICATION">%2$s</xliff:g> під’єднатися до мережі VPN. Цей додаток теж може відстежувати ваші дії в мережі."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Цим пристроєм керує \n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nАдміністратор може відстежувати ваші дії в мережі, зокрема листування, роботу в додатках і на захищених веб-сайтах. Щоб дізнатися більше, зверніться до адміністратора.\n\nВаш пристрій також під’єднаний до мережі VPN (<xliff:g id="APPLICATION">%2$s</xliff:g>). Постачальник послуг VPN може відстежувати ваші дії в мережі."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Пристрій залишатиметься заблокованим, доки ви не розблокуєте його вручну"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> вимикає звук"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 4d8cb7b..c46bd28 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"غیر مقفل کریں"</string>
     <string name="phone_label" msgid="2320074140205331708">"فون کھولیں"</string>
     <string name="camera_label" msgid="7261107956054836961">"کیمرا کھولیں"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"آلہ محفوظ ہے۔"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"آلہ محفوظ نہیں ہے۔"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"آلہ محفوظ ہے، ٹرسٹ ایجنٹ فعال ہے۔"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"آلہ محفوظ نہیں ہے، ٹرسٹ ایجنٹ فعال ہے۔"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"چہرے کی شناخت چل رہی ہے، ٹرسٹ ایجنٹ فعال ہے۔"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"اندراج کا طریقہ سوئچ کرنے کا بٹن۔"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"مطابقت پذیری زوم بٹن۔"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"چھوٹی سے بڑی اسکرین پر زوم کریں۔"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"‏اس آلہ کا نظم مندرجہ ذیل کے ذریعے کیا جاتا ہے:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nآپ کا منتظم آپ کے نیٹ ورک کی سرگرمی بشمول ای میلز، ایپس اور محفوظ ویب سائٹس کو مانیٹر کرنے کا اہل ہے۔ مزید معلومات کیلئے، اپنے منتظم سے رابطہ کریں۔\n\nنیز، آپ نے \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" کو ایک VPN کنکشن ترتیب دینے کی اجازت دی ہے۔ یہ ایپ نیٹ ورک کی سرگرمی بھی مانیٹر کر سکتی ہے۔"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"‏اس آلہ کا نظم مندرجہ ذیل کے ذریعے کیا جاتا ہے:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nآپ کا منتظم آپ کے نیٹ ورک کی سرگرمی بشمول ای میلز، ایپس اور محفوظ ویب سائٹس کو مانیٹر کرنے کا اہل ہے۔ مزید معلومات کیلئے، اپنے منتظم سے رابطہ کریں۔\n\nنیز، آپ ایک VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") سے منسلک ہیں۔ آپ کی VPN سروس کا فراہم کنندہ نیٹورک کی سرگرمی کو بھی مانیٹر کر سکتا ہے۔"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"آلہ اس وقت تک مقفل رہے گا جب تک آپ دستی طور پر اسے غیر مقفل نہ کریں"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> کے ذریعے خاموش کردہ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index df335e2..5a53f63 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"qulfdan chiqarish"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefonni ochish"</string>
     <string name="camera_label" msgid="7261107956054836961">"kamerani ochish"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Qurilma himoyalangan."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Qurilma himoyalanmagan."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Qurilma himoyalangan, ishonchli agent ishlab turibdi."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Qurilma himoyalanmagan, ishonchli agent ishlab turibdi."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Yuzingiz tekshirilmoqda, ishonchli agent ishlab turibdi."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Kiritish uslubi tugmasini almashtirish."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kattalashtirish tugmasi mosligi."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kattaroq ekran uchun kichikroqni kattalashtirish."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Bu qurilma boshqaruvchisi:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdmin-ngiz tarmoqdagi faollik – e-pochta, ilova va xavfsiz veb-saytlardagi harakat-ni kuzatishi m-n. Qo‘shimcha ma’lumot olish u-n admin-ga murojaat qiling.\n\nSiz “<xliff:g id="APPLICATION">%2$s</xliff:g>” ilovasiga VPN ulanishini sozlash u-n ruxsat berdingiz. U ham tarmoqdagi faolligingizni kuzatishi mumkin."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Bu qurilma boshqaruvchisi:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdmin-ngiz tarmoqdagi faollik – e-pochta, ilova va xavfsiz veb-saytlardagi harakat-ni kuzatishi m-n. Qo‘shimcha ma’lumot olish u-n admin-ga murojaat qiling.\n\nSiz VPN tarmog‘iga ham ulangansiz (“<xliff:g id="APPLICATION">%2$s</xliff:g>”). VPN xizmati ta’minotchingiz ham tarmoqdagi faollingizni kuzatishi m-n."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Qurilma qo‘lda qulfdan chiqarilmaguncha qulflangan holatda qoladi"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"“<xliff:g id="THIRD_PARTY">%1$s</xliff:g>” tomonidan ovozsiz qilingan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d21a371..61345bb 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"mở khóa"</string>
     <string name="phone_label" msgid="2320074140205331708">"mở điện thoại"</string>
     <string name="camera_label" msgid="7261107956054836961">"mở máy ảnh"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Thiết bị được bảo mật."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Thiết bị chưa được bảo mật."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Thiết bị được bảo mật, tác nhân đáng tin cậy đang hoạt động."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Thiết bị chưa được bảo mật, tác nhân đáng tin cậy đang hoạt động."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Đang chạy chức năng nhận diện khuôn mặt, tác nhân đáng tin cậy đang hoạt động."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Nút chuyển phương thức nhập."</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Nút thu phóng khả năng tương thích."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Thu phóng màn hình lớn hơn hoặc nhỏ hơn."</string>
@@ -193,10 +188,10 @@
     <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Đóng bảng điều khiển."</string>
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Nhiều thời gian hơn."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Ít thời gian hơn."</string>
-    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Đèn nháy tắt."</string>
-    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Đèn nháy bật."</string>
-    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Đã tắt đèn nháy."</string>
-    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Đã bật đèn nháy."</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Đèn pin tắt."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Đèn pin bật."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Đã tắt đèn pin."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Đã bật đèn pin."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Đã tắt đảo màu."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Đã bật đảo màu."</string>
     <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Đã tắt điểm phát sóng di động."</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Thiết bị này được quản lý bởi:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nQuản trị viên có thể giám sát hoạt động mạng gồm email, ứng dụng và trang web an toàn. Để biết thêm thông tin, hãy liên hệ với quản trị viên.\n\nNgoài ra, bạn đã cấp cho \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" quyền thiết lập kết nối VPN. Ứng dụng này có thể giám sát hoạt động mạng."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Thiết bị này được quản lý bởi:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nQuản trị viên có thể giám sát hoạt động mạng của bạn bao gồm email, ứng dụng và các trang web an toàn. Để biết thêm thông tin, hãy liên hệ với quản trị viên của bạn.\n\nNgoài ra, bạn được kết nối với VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Nhà cung cấp dịch vụ VPN cũng có thể giám sát hoạt động mạng."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Thiết bị sẽ vẫn bị khóa cho tới khi bạn mở khóa theo cách thủ công"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Do <xliff:g id="THIRD_PARTY">%1$s</xliff:g> tắt tiếng"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 35d8aa0..3cf2f23 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -84,12 +84,9 @@
     <string name="accessibility_search_light" msgid="1103867596330271848">"搜索"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"相机"</string>
     <string name="accessibility_phone_button" msgid="6738112589538563574">"电话"</string>
-    <!-- no translation found for unlock_label (8779712358041029439) -->
-    <skip />
-    <!-- no translation found for phone_label (2320074140205331708) -->
-    <skip />
-    <!-- no translation found for camera_label (7261107956054836961) -->
-    <skip />
+    <string name="unlock_label" msgid="8779712358041029439">"解锁"</string>
+    <string name="phone_label" msgid="2320074140205331708">"打开电话"</string>
+    <string name="camera_label" msgid="7261107956054836961">"打开相机"</string>
     <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
     <skip />
     <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
@@ -176,65 +173,37 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"最近浏览过的屏幕。"</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用户:<xliff:g id="USER">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>。"</string>
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_off (8716484460897819400) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_wifi_changed_on (6440117170789528622) -->
-    <skip />
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"WLAN已关闭。"</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"WLAN已开启。"</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"移动数据连接:<xliff:g id="SIGNAL">%1$s</xliff:g>,<xliff:g id="TYPE">%2$s</xliff:g>,<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"电池电量:<xliff:g id="STATE">%s</xliff:g>。"</string>
-    <!-- no translation found for accessibility_quick_settings_airplane_off (7786329360056634412) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_on (6406141469157599296) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_off (66846307818850664) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_airplane_changed_on (8983005603505087728) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_off (2133631372372064339) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_on (7681999166216621838) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connecting (6953242966685343855) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_connected (4306637793614573659) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_off (2730003763480934529) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_on (8722351798763206577) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_off (5119080556976115520) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_on (5809937096590102036) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_off (8526845571503387376) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_location_changed_on (339403053079338468) -->
-    <skip />
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"飞行模式关闭。"</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"飞行模式开启。"</string>
+    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"飞行模式已关闭。"</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"飞行模式已开启。"</string>
+    <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"蓝牙关闭。"</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"蓝牙开启。"</string>
+    <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"蓝牙连接中。"</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"蓝牙已连接。"</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"蓝牙已关闭。"</string>
+    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"蓝牙已开启。"</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"位置报告功能关闭。"</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"位置报告功能开启。"</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"位置报告功能已关闭。"</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"位置报告功能已开启。"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"闹钟已设置为:<xliff:g id="TIME">%s</xliff:g>。"</string>
-    <!-- no translation found for accessibility_quick_settings_close (3115847794692516306) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (3659274935356197708) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (2404728746293515623) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_off (4936432000069786988) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_on (2003479320007841077) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_off (3303701786768224304) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_flashlight_changed_on (6531793301533894686) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_off (4406577213290173911) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_on (6897462320184911126) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_off (5004708003447561394) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_hotspot_changed_on (2890951609226476206) -->
-    <skip />
-    <!-- no translation found for accessibility_casting_turned_off (1430668982271976172) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"关闭面板。"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"延长时间。"</string>
+    <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"缩短时间。"</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"手电筒关闭。"</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"手电筒打开。"</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"手电筒已关闭。"</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"手电筒已打开。"</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"颜色反转功能已关闭。"</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"颜色反转功能已开启。"</string>
+    <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"移动热点已关闭。"</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"移动热点已开启。"</string>
+    <string name="accessibility_casting_turned_off" msgid="1430668982271976172">"屏幕投射已停止。"</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"屏幕亮度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G数据网络已关闭"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G数据网络已关闭"</string>
@@ -252,12 +221,9 @@
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕锁定为横向模式。"</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕锁定为纵向模式。"</string>
-    <!-- no translation found for accessibility_rotation_lock_off_changed (8134601071026305153) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_landscape_changed (3135965553707519743) -->
-    <skip />
-    <!-- no translation found for accessibility_rotation_lock_on_portrait_changed (8922481981834012126) -->
-    <skip />
+    <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"屏幕将会自动旋转。"</string>
+    <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"屏幕现已锁定为横向模式。"</string>
+    <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"屏幕现已锁定为纵向模式。"</string>
     <string name="dessert_case" msgid="1295161776223959221">"甜品盒"</string>
     <string name="start_dreams" msgid="7219575858348719790">"互动屏保"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"有线网络"</string>
@@ -378,8 +344,7 @@
     <string name="vpn_footer" msgid="2388611096129106812">"网络可能会受到监控"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"设备监测"</string>
     <string name="monitoring_title" msgid="169206259253048106">"网络监控"</string>
-    <!-- no translation found for disable_vpn (4435534311510272506) -->
-    <skip />
+    <string name="disable_vpn" msgid="4435534311510272506">"关闭VPN"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"断开VPN连接"</string>
     <string name="monitoring_description_device_owned" msgid="7512371572956715493">"此设备由以下单位管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n您的管理员可以监控您的设备和网络活动,包括收发电子邮件、使用应用和浏览安全网站。\n\n若要了解详情,请与您的管理员联系。"</string>
     <string name="monitoring_description_vpn" msgid="7288268682714305659">"您已授权“<xliff:g id="APPLICATION">%1$s</xliff:g>”设置VPN连接。\n\n此应用可以监控您的设备和网络活动,包括收发电子邮件、使用应用和浏览安全网站。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 0e890140..41518a0 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"解鎖"</string>
     <string name="phone_label" msgid="2320074140205331708">"開啟電話"</string>
     <string name="camera_label" msgid="7261107956054836961">"開啟相機"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"裝置安全。"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"裝置不安全。"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"裝置安全,信任代理程式已啟用。"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"裝置不安全,信任代理程式已啟用。"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"臉孔偵測正在執行,信任代理程式已啟用。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
@@ -173,7 +168,7 @@
     <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"最近的螢幕。"</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用戶:<xliff:g id="USER">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>。"</string>
-    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi 已關閉。"</string>
+    <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"WiFi 已關閉。"</string>
     <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"WiFi 已開啟。"</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"流動數據連線:<xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="TYPE">%2$s</xliff:g>、<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池電量:<xliff:g id="STATE">%s</xliff:g>。"</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"這部裝置由下列網域管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n您的管理員可以監控您的網絡活動,包括收發電郵、使用應用程式和瀏覽安全網站。如需更多資料,請與您的管理員聯絡。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%2$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網絡活動。"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"這部裝置由下列網域管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n您的管理員可以監控您的網絡活動,包括收發電郵、使用應用程式和瀏覽安全網站。如需更多資料,請與您的管理員聯絡。\n\n同時,您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%2$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網絡活動。"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"裝置將保持上鎖,直到您手動解鎖"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"靜音設定者:<xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d4bfa6b..b47d766 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"解除鎖定"</string>
     <string name="phone_label" msgid="2320074140205331708">"開啟電話"</string>
     <string name="camera_label" msgid="7261107956054836961">"開啟攝影機"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"裝置安全。"</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"裝置不安全。"</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"裝置安全,信任的代理程式已啟用。"</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"裝置不安全,信任的代理程式已啟用。"</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"正在執行臉孔偵測,信任的代理程式已啟用。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
@@ -352,6 +347,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"這個裝置由下列網域管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%2$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網路活動。"</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"這個裝置由下列網域管理:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n您的管理員可以監控您的網路活動,包括收發電子郵件、使用應用程式和瀏覽安全網站。如需詳細資訊,請與您的管理員聯絡。\n\n同時,由於您的裝置已連線至 VPN (「<xliff:g id="APPLICATION">%2$s</xliff:g>」),因此您的 VPN 服務供應商也能監控您的網路活動。"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"在您手動解鎖前,裝置將保持鎖定狀態"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"由 <xliff:g id="THIRD_PARTY">%1$s</xliff:g> 設為靜音"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 496b4c88..63c1ac3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -87,16 +87,11 @@
     <string name="unlock_label" msgid="8779712358041029439">"vula"</string>
     <string name="phone_label" msgid="2320074140205331708">"vula ifoni"</string>
     <string name="camera_label" msgid="7261107956054836961">"vula ikhamera"</string>
-    <!-- no translation found for accessibility_unlock_button_secured (8165840811789635668) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured (7905679894326511625) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_secured_trust_managed (6463973986970587223) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_not_secured_trust_managed (419377005316443992) -->
-    <skip />
-    <!-- no translation found for accessibility_unlock_button_face_unlock_running (1144920873023669283) -->
-    <skip />
+    <string name="accessibility_unlock_button_secured" msgid="8165840811789635668">"Idivayisi ivikelekile."</string>
+    <string name="accessibility_unlock_button_not_secured" msgid="7905679894326511625">"Idivayisi ayivikelekile."</string>
+    <string name="accessibility_unlock_button_secured_trust_managed" msgid="6463973986970587223">"Idivayisi ivikelekile, isisebenzeli esethembekile siyasebenza."</string>
+    <string name="accessibility_unlock_button_not_secured_trust_managed" msgid="419377005316443992">"Idivayisi ayivikelekile, isisebenzeli esethembekile siyasebenza.."</string>
+    <string name="accessibility_unlock_button_face_unlock_running" msgid="1144920873023669283">"Ukutholakala kobuso kuyasebenza, isisebenzeli esethembekile siyasebenza."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Vula indlela yokungena yenkinobho"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Inkinobho evumelekile yokusondeza"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Sondeza kancane esikrinini esikhudlwana"</string>
@@ -350,6 +345,5 @@
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Le divayisi iphethwe i-:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nUmqondisi wakho uyakwazi ukwengamela umsebenzi wakho wenethiwekhi kufaka phakathi ama-imeyili, izinhlelo zokusebenza, namawebhusayithi aphephile. Ngolwazi olubanzi, xhumana nomqondisi wakho.\n\nFuthi, unike i-\"<xliff:g id="APPLICATION">%2$s</xliff:g>\" imvume yokusetha uxhumo le-VPN. Lolu hlelo lokusebenza lungangamela futhi umsebenzi wenethiwekhi."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Le divayisi iphathwe i-:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nUmqondisi wakho uyakwazi ukwengamela umsebenzi wenethiwekhi yakho kufaka phakathi ama-imeyili, izinhlelo zokusebenza, namawebhusayithi aphephile. Ngolwazi olubanzi, xhumana nomqondisi wakho.\n\nFuthi, uxhumekile ku-VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Umhlinzeki wakho wesevisi ye-VPN angangamela futhi umsebenzi wenethiwekhi."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Idivayisi izohlala ikhiyekile uze uyivule ngokwenza"</string>
-    <!-- no translation found for muted_by (6147073845094180001) -->
-    <skip />
+    <string name="muted_by" msgid="6147073845094180001">"Ithuliswe ngu-<xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e940b18..0e189792 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -62,6 +62,9 @@
     <!-- Vibration duration for GlowPadView used in SearchPanelView -->
     <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
 
+    <!-- Show camera affordance on Keyguard -->
+    <bool name="config_keyguardShowCameraAffordance">true</bool>
+
     <!-- The length of the vibration when the notification pops open. -->
     <integer name="one_finger_pop_duration_ms">10</integer>
 
@@ -123,10 +126,10 @@
     <!-- The min animation duration for animating views that are newly visible. -->
     <integer name="recents_filter_animate_new_views_duration">250</integer>
     <!-- The min animation duration for animating the task bar in. -->
-    <integer name="recents_animate_task_bar_enter_duration">275</integer>
+    <integer name="recents_animate_task_bar_enter_duration">225</integer>
     <!-- The animation delay for animating the first task in. This should roughly be the animation
      duration of the transition in to recents. -->
-    <integer name="recents_animate_task_bar_enter_delay">300</integer>
+    <integer name="recents_animate_task_bar_enter_delay">275</integer>
     <!-- The min animation duration for animating the task bar out. -->
     <integer name="recents_animate_task_exit_to_home_duration">225</integer>
     <!-- The min animation duration for animating the task bar out. -->
@@ -143,6 +146,8 @@
     <integer name="recents_nav_bar_scrim_enter_duration">400</integer>
     <!-- The animation duration for animating the removal of a task view. -->
     <integer name="recents_animate_task_view_remove_duration">250</integer>
+    <!-- The animation duration for scrolling the stack to a particular item. -->
+    <integer name="recents_animate_task_stack_scroll_duration">225</integer>
     <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
     <integer name="recents_max_task_stack_view_dim">96</integer>
     <!-- The delay to enforce between each alt-tab key press. -->
@@ -195,5 +200,8 @@
 
     <!-- Tiles with feature timeouts: number of days to show after feature is used. -->
     <integer name="days_to_show_timeout_tiles">30</integer>
+
+    <!-- Number of times to show the strong alarm warning text in the volume dialog -->
+    <integer name="zen_mode_alarm_warning_threshold">5</integer>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 0af693d..162c277 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -166,6 +166,7 @@
     <dimen name="qs_dual_tile_padding_vertical">8dp</dimen>
     <dimen name="qs_dual_tile_padding_horizontal">6dp</dimen>
     <dimen name="qs_tile_padding_top">16dp</dimen>
+    <dimen name="qs_tile_padding_top_large_text">4dp</dimen>
     <dimen name="qs_tile_padding_below_icon">12dp</dimen>
     <dimen name="qs_tile_padding_bottom">16dp</dimen>
     <dimen name="qs_tile_spacing">4dp</dimen>
@@ -173,7 +174,13 @@
     <dimen name="qs_detail_item_height">48dp</dimen>
     <dimen name="qs_detail_item_height_twoline">72dp</dimen>
     <dimen name="qs_brightness_padding_top">6dp</dimen>
-
+    <dimen name="qs_detail_header_text_size">20sp</dimen>
+    <dimen name="qs_detail_button_text_size">14sp</dimen>
+    <dimen name="qs_detail_item_primary_text_size">16sp</dimen>
+    <dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
+    <dimen name="qs_detail_empty_text_size">14sp</dimen>
+    <dimen name="qs_data_usage_text_size">14sp</dimen>
+    <dimen name="qs_data_usage_usage_text_size">36sp</dimen>
 
     <dimen name="segmented_button_spacing">4dp</dimen>
     <dimen name="segmented_button_radius">2dp</dimen>
@@ -195,17 +202,14 @@
     <!-- The size of the application icon in the recents task view. -->
     <dimen name="recents_task_view_application_icon_size">48dp</dimen>
 
-    <!-- The size of the activity icon in the recents task view. -->
-    <dimen name="recents_task_view_activity_icon_size">60dp</dimen>
-
     <!-- The radius of the rounded corners on a task view. -->
     <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
 
     <!-- The min translation in the Z index for the last task. -->
-    <dimen name="recents_task_view_z_min">25dp</dimen>
+    <dimen name="recents_task_view_z_min">20dp</dimen>
 
     <!-- The max translation in the Z index for the last task. -->
-    <dimen name="recents_task_view_z_max">100dp</dimen>
+    <dimen name="recents_task_view_z_max">80dp</dimen>
 
     <!-- The amount to translate when animating the removal of a task. -->
     <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
@@ -231,6 +235,9 @@
     <!-- The side padding for the task stack as a percentage of the width. -->
     <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.04444</item>
 
+    <!-- The overscroll percentage allowed on the stack. -->
+    <item name="recents_stack_overscroll_percentage" format="float" type="dimen">0.0875</item>
+
     <!-- The top offset for the task stack. -->
     <dimen name="recents_stack_top_padding">16dp</dimen>
 
@@ -278,8 +285,14 @@
     <!-- The height of the speed bump view. -->
     <dimen name="speed_bump_height">16dp</dimen>
 
-    <!-- Lockscreen affordance drag distance for camera and phone. -->
-    <dimen name="affordance_drag_distance">100dp</dimen>
+    <!-- Lockscreen unlocking falsing threshold. -->
+    <dimen name="unlock_falsing_threshold">100dp</dimen>
+
+    <!-- Lockscreen falsing threshold for quick settings. -->
+    <dimen name="qs_falsing_threshold">60dp</dimen>
+
+    <!-- Falsing threshold used when dismissing notifications from the lockscreen. -->
+    <dimen name="swipe_helper_falsing_threshold">100dp</dimen>
 
     <dimen name="notifications_top_padding">8dp</dimen>
     
@@ -299,7 +312,7 @@
     <dimen name="heads_up_window_height">250dp</dimen>
 
     <!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
-    <dimen name="keyguard_min_swipe_amount">75dp</dimen>
+    <dimen name="keyguard_min_swipe_amount">85dp</dimen>
 
     <!-- The minimum background radius when swiping to a side for the camera / phone affordances. -->
     <dimen name="keyguard_affordance_min_background_radius">30dp</dimen>
@@ -362,6 +375,9 @@
     <!-- The padding bottom of the clock group when QS is collapsed. -->
     <dimen name="clock_collapsed_bottom_margin">10dp</dimen>
 
+    <!-- The padding bottom of the clock group when QS is collapsed for large text -->
+    <dimen name="clock_collapsed_bottom_margin_large_text">6dp</dimen>
+
     <!-- The width of the multi user switch on keyguard and collapsed QS header. -->
     <dimen name="multi_user_switch_width_collapsed">34dp</dimen>
 
@@ -383,6 +399,12 @@
     <!-- The font size of the time when expanded in QS -->
     <dimen name="qs_time_expanded_size">20sp</dimen>
 
+    <!-- The font size of the "emergency calls only" label in QS -->
+    <dimen name="qs_emergency_calls_only_text_size">12sp</dimen>
+
+    <!-- The font size of the date in QS -->
+    <dimen name="qs_date_collapsed_size">14sp</dimen>
+
     <!-- Battery level padding end when in expanded QS (but not on Keyguard) -->
     <dimen name="battery_level_padding_end">4dp</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 120af1d..07943e1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -213,6 +213,8 @@
     <string name="accessibility_camera_button">Camera</string>
     <!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_phone_button">Phone</string>
+    <!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button">Unlock</string>
     <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
     <string name="unlock_label">unlock</string>
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
@@ -220,17 +222,6 @@
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
     <string name="camera_label">open camera</string>
 
-    <!-- Content description of the lock icon when device is secured (lock closed) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button_secured">Device secured.</string>
-    <!-- Content description of the lock icon when device is not secured (lock open) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button_not_secured">Device not secured.</string>
-    <!-- Content description of the lock icon when device is secured (lock closed) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button_secured_trust_managed">Device secured, trust agent active.</string>
-    <!-- Content description of the lock icon when device is not secured (lock open) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button_not_secured_trust_managed">Device not secured, trust agent active.</string>
-    <!-- Content description of the lock icon when face unlock is running (face icon) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_unlock_button_face_unlock_running">Face detection running, trust agent active.</string>
-
     <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ime_switch_button">Switch input method button.</string>
     <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -392,6 +383,9 @@
     <!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ringer_silent">Ringer silent.</string>
 
+    <!-- Content description of the cast icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_casting">@string/quick_settings_casting</string>
+
     <!-- Content description to tell the user that this button will remove an application from recents -->
     <string name="accessibility_recents_item_will_be_dismissed">Dismiss <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
     <!-- Content description to tell the user an application has been removed from recents -->
@@ -694,7 +688,7 @@
     <string name="description_direction_left">"Slide left for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
 
     <!-- Zen mode: No interruptions title, with a warning about alarms. [CHAR LIMIT=60] -->
-    <string name="zen_no_interruptions_with_warning">No interruptions, including alarms</string>
+    <string name="zen_no_interruptions_with_warning">No interruptions. Not even alarms.</string>
 
     <!-- Zen mode: No interruptions. [CHAR LIMIT=40] -->
     <string name="zen_no_interruptions">No interruptions</string>
@@ -834,12 +828,18 @@
     <!-- Footer device owned text [CHAR LIMIT=50] -->
     <string name="device_owned_footer">Device may be monitored</string>
 
+    <!-- Footer profile owned text [CHAR LIMIT=50] -->
+    <string name="profile_owned_footer">Profile may be monitored</string>
+
     <!-- Footer vpn present text [CHAR LIMIT=50] -->
     <string name="vpn_footer">Network may be monitored</string>
 
     <!-- Monitoring dialog title for device owned devices [CHAR LIMIT=35] -->
     <string name="monitoring_title_device_owned">Device monitoring</string>
 
+    <!-- Monitoring dialog title for profile owned devices [CHAR LIMIT=35] -->
+    <string name="monitoring_title_profile_owned">Profile monitoring</string>
+
     <!-- Monitoring dialog title for normal devices  [CHAR LIMIT=35]-->
     <string name="monitoring_title">Network monitoring</string>
 
@@ -864,6 +864,24 @@
     <!-- Monitoring dialog legacy VPN with device owner text [CHAR LIMIT=300] -->
     <string name="monitoring_description_legacy_vpn_device_owned">This device is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites. For more information, contact your administrator.\n\nAlso, you\'re connected to a VPN (\"<xliff:g id="application">%2$s</xliff:g>\"). Your VPN service provider can monitor network activity too.</string>
 
+    <!-- Monitoring dialog profile owner body text [CHAR LIMIT=300] -->
+    <string name="monitoring_description_profile_owned">This profile is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\n\nYour administrator can monitor your device and network activity, including emails, apps and secure websites.\n\nFor more information, contact your administrator.</string>
+
+    <!-- Monitoring dialog device and profile owner body text [CHAR LIMIT=300] -->
+    <string name="monitoring_description_device_and_profile_owned">This device is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\nYour profile is managed by:\n<xliff:g id="organization">%2$s</xliff:g>\n\nYour administrator can monitor your device and network activity, including emails, apps and secure websites.\n\nFor more information, contact your administrator.</string>
+
+    <!-- Monitoring dialog non-legacy VPN with profile owner text [CHAR LIMIT=300] -->
+    <string name="monitoring_description_vpn_profile_owned">This profile is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites. For more information, contact your administrator.\n\nAlso, you gave \"<xliff:g id="application">%2$s</xliff:g>\" permission to set up a VPN connection. This app can monitor network activity too.</string>
+
+    <!-- Monitoring dialog legacy VPN with profile owner text [CHAR LIMIT=300] -->
+    <string name="monitoring_description_legacy_vpn_profile_owned">This profile is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites. For more information, contact your administrator.\n\nAlso, you\'re connected to a VPN (\"<xliff:g id="application">%2$s</xliff:g>\"). Your VPN service provider can monitor network activity too.</string>
+
+    <!-- Monitoring dialog non-legacy VPN with device and profile owner text [CHAR LIMIT=300] -->
+    <string name="monitoring_description_vpn_device_and_profile_owned">This device is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\nYour profile is managed by:\n<xliff:g id="organization">%2$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites. For more information, contact your administrator.\n\nAlso, you gave \"<xliff:g id="application">%3$s</xliff:g>\" permission to set up a VPN connection. This app can monitor network activity too.</string>
+
+    <!-- Monitoring dialog legacy VPN with device and profile owner text [CHAR LIMIT=300] -->
+    <string name="monitoring_description_legacy_vpn_device_and_profile_owned">This device is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\nYour profile is managed by:\n<xliff:g id="organization">%2$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites. For more information, contact your administrator.\n\nAlso, you\'re connected to a VPN (\"<xliff:g id="application">%3$s</xliff:g>\"). Your VPN service provider can monitor network activity too.</string>
+
     <!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] -->
     <string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b39fe24..efd4fb4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -33,8 +33,7 @@
         <item name="android:navigationBarColor">@android:color/transparent</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
         <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
-
-        <item name="android:ambientShadowAlpha">0.30</item>
+        <item name="android:ambientShadowAlpha">0.35</item>
     </style>
 
     <!-- Animations for a non-full-screen window or activity. -->
@@ -85,13 +84,13 @@
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.Date">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">@dimen/qs_date_collapsed_size</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">#b2ffffff</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
-        <item name="android:textSize">12dp</item>
+        <item name="android:textSize">@dimen/qs_emergency_calls_only_text_size</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">#66ffffff</item>
     </style>
@@ -125,16 +124,16 @@
     </style>
 
     <style name="TextAppearance.QS.DetailHeader">
-        <item name="android:textSize">20sp</item>
+        <item name="android:textSize">@dimen/qs_detail_header_text_size</item>
         <item name="android:fontFamily">sans-serif-medium</item>
     </style>
 
     <style name="TextAppearance.QS.DetailItemPrimary">
-        <item name="android:textSize">16sp</item>
+        <item name="android:textSize">@dimen/qs_detail_item_primary_text_size</item>
     </style>
 
     <style name="TextAppearance.QS.DetailItemSecondary">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
         <item name="android:textColor">@color/system_accent_color</item>
     </style>
 
@@ -144,14 +143,14 @@
     </style>
 
     <style name="TextAppearance.QS.DetailButton">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">@dimen/qs_detail_button_text_size</item>
         <item name="android:textAllCaps">true</item>
         <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:gravity">center</item>
     </style>
 
     <style name="TextAppearance.QS.DetailEmpty">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">@dimen/qs_detail_empty_text_size</item>
         <item name="android:textColor">@color/qs_subhead</item>
     </style>
 
@@ -167,11 +166,11 @@
     </style>
 
     <style name="TextAppearance.QS.DataUsage">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textSize">@dimen/qs_data_usage_text_size</item>
     </style>
 
     <style name="TextAppearance.QS.DataUsage.Usage">
-        <item name="android:textSize">36sp</item>
+        <item name="android:textSize">@dimen/qs_data_usage_usage_text_size</item>
         <item name="android:textColor">@color/system_accent_color</item>
     </style>
 
@@ -235,8 +234,8 @@
         <item name="android:windowExitAnimation">@*android:anim/popup_exit_material</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Material.EventContent.Parenthetical"
-           parent="@*android:style/TextAppearance.StatusBar.Material.EventContent">
+    <style name="TextAppearance.Material.Notification.Parenthetical"
+           parent="@*android:style/TextAppearance.Material.Notification">
         <item name="android:textStyle">italic</item>
         <item name="android:textColor">#60000000</item>
     </style>
diff --git a/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java b/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java
new file mode 100644
index 0000000..35a70a5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.systemui;
+
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Utility class to update the font size when the configuration has changed.
+ */
+public class FontSizeUtils {
+
+    public static final float LARGE_TEXT_SCALE = 1.3f;
+
+    public static void updateFontSize(View parent, int viewId, int dimensId) {
+        updateFontSize((TextView) parent.findViewById(viewId), dimensId);
+    }
+
+    public static void updateFontSize(TextView v, int dimensId) {
+        if (v != null) {
+            v.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                    v.getResources().getDimensionPixelSize(dimensId));
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index a18b0c0..8e603ba 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -81,6 +81,8 @@
     private long mLongPressTimeout;
 
     final private int[] mTmpPos = new int[2];
+    private int mFalsingThreshold;
+    private boolean mTouchAboveFalsingThreshold;
 
     public SwipeHelper(int swipeDirection, Callback callback, Context context) {
         mCallback = callback;
@@ -93,6 +95,8 @@
         mLongPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f); // extra long-press!
         mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
                 android.R.interpolator.fast_out_linear_in);
+        mFalsingThreshold = context.getResources().getDimensionPixelSize(
+                R.dimen.swipe_helper_falsing_threshold);
     }
 
     public void setLongPressListener(LongPressListener listener) {
@@ -222,6 +226,7 @@
 
         switch (action) {
             case MotionEvent.ACTION_DOWN:
+                mTouchAboveFalsingThreshold = false;
                 mDragging = false;
                 mLongPressSent = false;
                 mCurrView = mCallback.getChildAtPosition(ev);
@@ -406,12 +411,16 @@
             case MotionEvent.ACTION_MOVE:
                 if (mCurrView != null) {
                     float delta = getPos(ev) - mInitialTouchPos;
+                    float absDelta = Math.abs(delta);
+                    if (absDelta >= mFalsingThreshold) {
+                        mTouchAboveFalsingThreshold = true;
+                    }
                     // don't let items that can't be dismissed be dragged more than
                     // maxScrollDistance
                     if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
                         float size = getSize(mCurrAnimView);
                         float maxScrollDistance = 0.15f * size;
-                        if (Math.abs(delta) >= size) {
+                        if (absDelta >= size) {
                             delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
                         } else {
                             delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
@@ -437,9 +446,11 @@
                     boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
                             (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
                             (velocity > 0) == (getTranslation(mCurrAnimView) > 0);
+                    boolean falsingDetected = mCallback.isAntiFalsingNeeded()
+                            && !mTouchAboveFalsingThreshold;
 
-                    boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) &&
-                            (childSwipedFastEnough || childSwipedFarEnough);
+                    boolean dismissChild = mCallback.canChildBeDismissed(mCurrView)
+                            && !falsingDetected && (childSwipedFastEnough || childSwipedFarEnough);
 
                     if (dismissChild) {
                         // flingadingy
@@ -462,6 +473,8 @@
 
         boolean canChildBeDismissed(View v);
 
+        boolean isAntiFalsingNeeded();
+
         void onBeginDrag(View v);
 
         void onChildDismissed(View v);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index 24c1378..ce0d5f4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -17,12 +17,14 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -31,6 +33,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 
 /**
@@ -76,6 +79,20 @@
         mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
+        int count = mItems.getChildCount();
+        for (int i = 0; i < count; i++) {
+            View item = mItems.getChildAt(i);
+            FontSizeUtils.updateFontSize(item, android.R.id.title,
+                    R.dimen.qs_detail_item_primary_text_size);
+            FontSizeUtils.updateFontSize(item, android.R.id.summary,
+                    R.dimen.qs_detail_item_secondary_text_size);
+        }
+    }
+
     public void setTagSuffix(String suffix) {
         mTag = TAG + "." + suffix;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index a8199fa..a0b6e82 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -18,23 +18,23 @@
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.res.Configuration;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
-import android.view.ContextThemeWrapper;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.WindowManager;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.SecurityController.VpnCallback;
 
 public class QSFooter implements OnClickListener, DialogInterface.OnClickListener {
     protected static final String TAG = "QSFooter";
@@ -50,6 +50,7 @@
     private AlertDialog mDialog;
     private QSTileHost mHost;
     private Handler mHandler;
+    private final Handler mMainHandler;
 
     private boolean mIsVisible;
     private boolean mIsIconVisible;
@@ -62,6 +63,7 @@
         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
         mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
         mContext = context;
+        mMainHandler = new Handler();
     }
 
     public void setHost(QSTileHost host) {
@@ -78,6 +80,10 @@
         }
     }
 
+    public void onConfigurationChanged() {
+        FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
+    }
+
     public View getView() {
         return mRootView;
     }
@@ -106,14 +112,19 @@
             mFooterTextId = R.string.device_owned_footer;
             mIsVisible = true;
             mIsIconVisible = false;
+        } else if (mSecurityController.hasProfileOwner()) {
+            mFooterTextId = R.string.profile_owned_footer;
+            mIsVisible = true;
+            mIsIconVisible = false;
         } else if (mSecurityController.isVpnEnabled()) {
             mFooterTextId = R.string.vpn_footer;
             mIsVisible = true;
             mIsIconVisible = true;
         } else {
             mIsVisible = false;
+            mIsIconVisible = false;
         }
-        mRootView.post(mUpdateDisplayState);
+        mMainHandler.post(mUpdateDisplayState);
     }
 
     @Override
@@ -148,20 +159,61 @@
 
     private String getMessage() {
         if (mSecurityController.hasDeviceOwner()) {
+            if (mSecurityController.hasProfileOwner()) {
+                if (mSecurityController.isVpnEnabled()) {
+                    if (mSecurityController.isLegacyVpn()) {
+                        return mContext.getString(
+                                R.string.monitoring_description_legacy_vpn_device_and_profile_owned,
+                                mSecurityController.getDeviceOwnerName(),
+                                mSecurityController.getProfileOwnerName(),
+                                mSecurityController.getLegacyVpnName());
+                    } else {
+                        return mContext.getString(
+                                R.string.monitoring_description_vpn_device_and_profile_owned,
+                                mSecurityController.getDeviceOwnerName(),
+                                mSecurityController.getProfileOwnerName(),
+                                mSecurityController.getVpnApp());
+                    }
+                } else {
+                    return mContext.getString(
+                            R.string.monitoring_description_device_and_profile_owned,
+                            mSecurityController.getDeviceOwnerName(),
+                            mSecurityController.getProfileOwnerName());
+                }
+            } else {
+                if (mSecurityController.isVpnEnabled()) {
+                    if (mSecurityController.isLegacyVpn()) {
+                        return mContext.getString(
+                                R.string.monitoring_description_legacy_vpn_device_owned,
+                                mSecurityController.getDeviceOwnerName(),
+                                mSecurityController.getLegacyVpnName());
+                    } else {
+                        return mContext.getString(R.string.monitoring_description_vpn_device_owned,
+                                mSecurityController.getDeviceOwnerName(),
+                                mSecurityController.getVpnApp());
+                    }
+                } else {
+                    return mContext.getString(R.string.monitoring_description_device_owned,
+                            mSecurityController.getDeviceOwnerName());
+                }
+            }
+        } else if (mSecurityController.hasProfileOwner()) {
             if (mSecurityController.isVpnEnabled()) {
                 if (mSecurityController.isLegacyVpn()) {
                     return mContext.getString(
-                            R.string.monitoring_description_legacy_vpn_device_owned,
-                            mSecurityController.getDeviceOwnerName(),
+                            R.string.monitoring_description_legacy_vpn_profile_owned,
+                            mSecurityController.getProfileOwnerName(),
                             mSecurityController.getLegacyVpnName());
                 } else {
-                    return mContext.getString(R.string.monitoring_description_vpn_device_owned,
-                            mSecurityController.getDeviceOwnerName(),
+                    return mContext.getString(
+                            R.string.monitoring_description_vpn_profile_owned,
+                            mSecurityController.getProfileOwnerName(),
                             mSecurityController.getVpnApp());
                 }
             } else {
-                return mContext.getString(R.string.monitoring_description_device_owned,
-                        mSecurityController.getDeviceOwnerName());
+                return mContext.getString(
+                        R.string.monitoring_description_profile_owned,
+                        mSecurityController.getProfileOwnerName());
             }
         } else {
             if (mSecurityController.isLegacyVpn()) {
@@ -179,6 +231,9 @@
         if (mSecurityController.hasDeviceOwner()) {
             return R.string.monitoring_title_device_owned;
         }
+        if (mSecurityController.hasProfileOwner()) {
+            return R.string.monitoring_title_profile_owned;
+        }
         return R.string.monitoring_title;
     }
 
@@ -193,9 +248,9 @@
         }
     };
 
-    private class Callback implements VpnCallback {
+    private class Callback implements SecurityController.SecurityControllerCallback {
         @Override
-        public void onVpnStateChanged() {
+        public void onStateChanged() {
             refreshState();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index a2136d2..6bfe0a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -21,15 +21,19 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Message;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+import android.widget.TextView;
 
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.DetailAdapter;
 import com.android.systemui.settings.BrightnessController;
@@ -48,8 +52,8 @@
     private final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
     private final View mDetail;
     private final ViewGroup mDetailContent;
-    private final View mDetailSettingsButton;
-    private final View mDetailDoneButton;
+    private final TextView mDetailSettingsButton;
+    private final TextView mDetailDoneButton;
     private final View mBrightnessView;
     private final QSDetailClipper mClipper;
     private final H mHandler = new H();
@@ -83,8 +87,8 @@
 
         mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false);
         mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
-        mDetailSettingsButton = mDetail.findViewById(android.R.id.button2);
-        mDetailDoneButton = mDetail.findViewById(android.R.id.button1);
+        mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
+        mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
         mDetail.setVisibility(GONE);
         mDetail.setClickable(true);
         mBrightnessView = LayoutInflater.from(context).inflate(
@@ -148,6 +152,24 @@
         }
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        FontSizeUtils.updateFontSize(mDetailDoneButton, R.dimen.qs_detail_button_text_size);
+        FontSizeUtils.updateFontSize(mDetailSettingsButton, R.dimen.qs_detail_button_text_size);
+
+        // We need to poke the detail views as well as they might not be attached to the view
+        // hierarchy but reused at a later point.
+        int count = mRecords.size();
+        for (int i = 0; i < count; i++) {
+            View detailView = mRecords.get(i).detailView;
+            if (detailView != null) {
+                detailView.dispatchConfigurationChanged(newConfig);
+            }
+        }
+        mFooter.onConfigurationChanged();
+    }
+
     public void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
@@ -401,16 +423,23 @@
         mBrightnessView.layout(0, mBrightnessPaddingTop,
                 mBrightnessView.getMeasuredWidth(),
                 mBrightnessPaddingTop + mBrightnessView.getMeasuredHeight());
+        boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
         for (TileRecord record : mRecords) {
             if (record.tileView.getVisibility() == GONE) continue;
             final int cols = getColumnCount(record.row);
             final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth;
             final int extra = (w - cw * cols) / (cols + 1);
-            final int left = record.col * cw + (record.col + 1) * extra;
+            int left = record.col * cw + (record.col + 1) * extra;
             final int top = getRowTop(record.row);
-            record.tileView.layout(left, top,
-                    left + record.tileView.getMeasuredWidth(),
-                    top + record.tileView.getMeasuredHeight());
+            int right;
+            int tileWith = record.tileView.getMeasuredWidth();
+            if (isRtl) {
+                right = w - left;
+                left = right - tileWith;
+            } else {
+                right = left + tileWith;
+            }
+            record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
         }
         final int dh = Math.max(mDetail.getMeasuredHeight(), getMeasuredHeight());
         mDetail.layout(0, 0, mDetail.getMeasuredWidth(), dh);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 876652c..2b071cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -306,6 +306,7 @@
         public String label;
         public String contentDescription;
         public String dualLabelContentDescription;
+        public boolean autoMirrorDrawable = true;
 
         public boolean copyTo(State other) {
             if (other == null) throw new IllegalArgumentException();
@@ -315,6 +316,7 @@
                     || !Objects.equals(other.icon, icon)
                     || !Objects.equals(other.label, label)
                     || !Objects.equals(other.contentDescription, contentDescription)
+                    || !Objects.equals(other.autoMirrorDrawable, autoMirrorDrawable)
                     || !Objects.equals(other.dualLabelContentDescription,
                     dualLabelContentDescription);
             other.visible = visible;
@@ -323,6 +325,7 @@
             other.label = label;
             other.contentDescription = contentDescription;
             other.dualLabelContentDescription = dualLabelContentDescription;
+            other.autoMirrorDrawable = autoMirrorDrawable;
             return changed;
         }
 
@@ -339,6 +342,7 @@
             sb.append(",label=").append(label);
             sb.append(",contentDescription=").append(contentDescription);
             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
+            sb.append(",autoMirrorDrawable=").append(autoMirrorDrawable);
             return sb.append(']');
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 20fd5a0..e6175d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Typeface;
@@ -25,6 +26,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.util.MathUtils;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.View;
@@ -33,6 +35,7 @@
 import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
 
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.State;
 
@@ -47,7 +50,7 @@
     private final H mHandler = new H();
     private final int mIconSizePx;
     private final int mTileSpacingPx;
-    private final int mTilePaddingTopPx;
+    private int mTilePaddingTopPx;
     private final int mTilePaddingBelowIconPx;
     private final int mDualTileVerticalPaddingPx;
     private final View mTopBackgroundView;
@@ -66,7 +69,6 @@
         final Resources res = context.getResources();
         mIconSizePx = res.getDimensionPixelSize(R.dimen.qs_tile_icon_size);
         mTileSpacingPx = res.getDimensionPixelSize(R.dimen.qs_tile_spacing);
-        mTilePaddingTopPx = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top);
         mTilePaddingBelowIconPx =  res.getDimensionPixelSize(R.dimen.qs_tile_padding_below_icon);
         mDualTileVerticalPaddingPx =
                 res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical);
@@ -86,6 +88,29 @@
         addView(mDivider);
 
         setClickable(true);
+
+        updateTopPadding();
+    }
+
+    private void updateTopPadding() {
+        Resources res = getResources();
+        int padding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top);
+        int largePadding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top_large_text);
+        float largeFactor = (MathUtils.constrain(getResources().getConfiguration().fontScale,
+                1.0f, FontSizeUtils.LARGE_TEXT_SCALE) - 1f) / (FontSizeUtils.LARGE_TEXT_SCALE - 1f);
+        mTilePaddingTopPx = Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
+        requestLayout();
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateTopPadding();
+        FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size);
+        if (mDualLabel != null) {
+            mDualLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                    getResources().getDimensionPixelSize(R.dimen.qs_tile_text_size));
+        }
     }
 
     private void recreateLabel() {
@@ -265,6 +290,10 @@
             } else if (state.iconId > 0) {
                 iv.setImageResource(state.iconId);
             }
+            Drawable drawable = iv.getDrawable();
+            if (state.autoMirrorDrawable && drawable != null) {
+                drawable.setAutoMirrored(true);
+            }
         }
         if (mDual) {
             mDualLabel.setText(state.label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 1df3d20..0ecdeaa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -18,6 +18,7 @@
 
 import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -78,10 +79,19 @@
     }
 
     private void layoutIndicator(View indicator) {
+        boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+        int left, right;
+        if (isRtl) {
+            right = mIconFrame.getLeft();
+            left = right - indicator.getMeasuredWidth();
+        } else {
+            left = mIconFrame.getRight();
+            right = left + indicator.getMeasuredWidth();
+        }
         indicator.layout(
-                mIconFrame.getRight(),
+                left,
                 mIconFrame.getBottom() - indicator.getMeasuredHeight(),
-                mIconFrame.getRight() + indicator.getMeasuredWidth(),
+                right,
                 mIconFrame.getBottom());
     }
 
@@ -96,6 +106,10 @@
         } else {
             mOverlay.setVisibility(GONE);
         }
+        Drawable drawable = mSignal.getDrawable();
+        if (state.autoMirrorDrawable && drawable != null) {
+            drawable.setAutoMirrored(true);
+        }
         final boolean shown = isShown();
         setVisibility(mIn, shown, s.activityIn);
         setVisibility(mOut, shown, s.activityOut);
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 109237b..0b83878 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -88,6 +88,7 @@
         final boolean connecting = mController.isBluetoothConnecting();
         state.visible = supported;
         state.value = enabled;
+        state.autoMirrorDrawable = false;
         if (enabled) {
             state.label = null;
             if (connected) {
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 f503657..8304291 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -93,6 +93,7 @@
         state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
         state.label = mContext.getString(R.string.quick_settings_cast_title);
         state.value = false;
+        state.autoMirrorDrawable = false;
         final Set<CastDevice> devices = mController.getCastDevices();
         boolean connecting = false;
         for (CastDevice device : devices) {
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 ce42d47..98adf81 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -95,6 +95,7 @@
                 : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
                 : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
                 : R.drawable.ic_qs_signal_no_signal;
+        state.autoMirrorDrawable = !cb.noSim;
         state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
                 ? cb.dataTypeIconId
                 : 0;
@@ -189,11 +190,6 @@
     };
 
     private final class CellularDetailAdapter implements DetailAdapter {
-        private static final double KB = 1024;
-        private static final double MB = 1024 * KB;
-        private static final double GB = 1024 * MB;
-
-        private final DecimalFormat FORMAT = new DecimalFormat("#.##");
 
         @Override
         public int getTitle() {
@@ -217,80 +213,17 @@
 
         @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
-            final View v = convertView != null ? convertView : LayoutInflater.from(mContext)
-                    .inflate(R.layout.data_usage, parent, false);
+            final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
+                    ? convertView
+                    : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
             final DataUsageInfo info = mController.getDataUsageInfo();
             if (info == null) return v;
-            final Resources res = mContext.getResources();
-            final int titleId;
-            final long bytes;
-            int usageColor = R.color.system_accent_color;
-            final String top;
-            String bottom = null;
-            if (info.usageLevel < info.warningLevel || info.limitLevel <= 0) {
-                // under warning, or no limit
-                titleId = R.string.quick_settings_cellular_detail_data_usage;
-                bytes = info.usageLevel;
-                top = res.getString(R.string.quick_settings_cellular_detail_data_warning,
-                        formatBytes(info.warningLevel));
-            } else if (info.usageLevel <= info.limitLevel) {
-                // over warning, under limit
-                titleId = R.string.quick_settings_cellular_detail_remaining_data;
-                bytes = info.limitLevel - info.usageLevel;
-                top = res.getString(R.string.quick_settings_cellular_detail_data_used,
-                        formatBytes(info.usageLevel));
-                bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
-                        formatBytes(info.limitLevel));
-            } else {
-                // over limit
-                titleId = R.string.quick_settings_cellular_detail_over_limit;
-                bytes = info.usageLevel - info.limitLevel;
-                top = res.getString(R.string.quick_settings_cellular_detail_data_used,
-                        formatBytes(info.usageLevel));
-                bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
-                        formatBytes(info.limitLevel));
-                usageColor = R.color.system_warning_color;
-            }
-
-            final TextView title = (TextView) v.findViewById(android.R.id.title);
-            title.setText(titleId);
-            final TextView usage = (TextView) v.findViewById(R.id.usage_text);
-            usage.setText(formatBytes(bytes));
-            usage.setTextColor(res.getColor(usageColor));
-            final DataUsageGraph graph = (DataUsageGraph) v.findViewById(R.id.usage_graph);
-            graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
-            final TextView carrier = (TextView) v.findViewById(R.id.usage_carrier_text);
-            carrier.setText(info.carrier);
-            final TextView period = (TextView) v.findViewById(R.id.usage_period_text);
-            period.setText(info.period);
-            final TextView infoTop = (TextView) v.findViewById(R.id.usage_info_top_text);
-            infoTop.setVisibility(top != null ? View.VISIBLE : View.GONE);
-            infoTop.setText(top);
-            final TextView infoBottom = (TextView) v.findViewById(R.id.usage_info_bottom_text);
-            infoBottom.setVisibility(bottom != null ? View.VISIBLE : View.GONE);
-            infoBottom.setText(bottom);
+            v.bind(info);
             return v;
         }
 
         public void setMobileDataEnabled(boolean enabled) {
             fireToggleStateChanged(enabled);
         }
-
-        private String formatBytes(long bytes) {
-            final long b = Math.abs(bytes);
-            double val;
-            String suffix;
-            if (b > 100 * MB) {
-                val = b / GB;
-                suffix = "GB";
-            } else if (b > 100 * KB) {
-                val = b / MB;
-                suffix = "MB";
-            } else {
-                val = b / KB;
-                suffix = "KB";
-            }
-            return FORMAT.format(val * (bytes < 0 ? -1 : 1)) + " " + suffix;
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
new file mode 100644
index 0000000..7bdb58f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -0,0 +1,131 @@
+/*
+ * 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 com.android.systemui.qs.tiles;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.FontSizeUtils;
+import com.android.systemui.R;
+import com.android.systemui.qs.DataUsageGraph;
+import com.android.systemui.statusbar.policy.NetworkController;
+
+import java.text.DecimalFormat;
+
+/**
+ * Layout for the data usage detail in quick settings.
+ */
+public class DataUsageDetailView extends LinearLayout {
+
+    private static final double KB = 1024;
+    private static final double MB = 1024 * KB;
+    private static final double GB = 1024 * MB;
+
+    private final DecimalFormat FORMAT = new DecimalFormat("#.##");
+
+    public DataUsageDetailView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        FontSizeUtils.updateFontSize(this, android.R.id.title, R.dimen.qs_data_usage_text_size);
+        FontSizeUtils.updateFontSize(this, R.id.usage_text, R.dimen.qs_data_usage_usage_text_size);
+        FontSizeUtils.updateFontSize(this, R.id.usage_carrier_text,
+                R.dimen.qs_data_usage_text_size);
+        FontSizeUtils.updateFontSize(this, R.id.usage_info_top_text,
+                R.dimen.qs_data_usage_text_size);
+        FontSizeUtils.updateFontSize(this, R.id.usage_period_text, R.dimen.qs_data_usage_text_size);
+        FontSizeUtils.updateFontSize(this, R.id.usage_info_bottom_text,
+                R.dimen.qs_data_usage_text_size);
+    }
+
+    public void bind(NetworkController.DataUsageInfo info) {
+        final Resources res = mContext.getResources();
+        final int titleId;
+        final long bytes;
+        int usageColor = R.color.system_accent_color;
+        final String top;
+        String bottom = null;
+        if (info.usageLevel < info.warningLevel || info.limitLevel <= 0) {
+            // under warning, or no limit
+            titleId = R.string.quick_settings_cellular_detail_data_usage;
+            bytes = info.usageLevel;
+            top = res.getString(R.string.quick_settings_cellular_detail_data_warning,
+                    formatBytes(info.warningLevel));
+        } else if (info.usageLevel <= info.limitLevel) {
+            // over warning, under limit
+            titleId = R.string.quick_settings_cellular_detail_remaining_data;
+            bytes = info.limitLevel - info.usageLevel;
+            top = res.getString(R.string.quick_settings_cellular_detail_data_used,
+                    formatBytes(info.usageLevel));
+            bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
+                    formatBytes(info.limitLevel));
+        } else {
+            // over limit
+            titleId = R.string.quick_settings_cellular_detail_over_limit;
+            bytes = info.usageLevel - info.limitLevel;
+            top = res.getString(R.string.quick_settings_cellular_detail_data_used,
+                    formatBytes(info.usageLevel));
+            bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
+                    formatBytes(info.limitLevel));
+            usageColor = R.color.system_warning_color;
+        }
+
+        final TextView title = (TextView) findViewById(android.R.id.title);
+        title.setText(titleId);
+        final TextView usage = (TextView) findViewById(R.id.usage_text);
+        usage.setText(formatBytes(bytes));
+        usage.setTextColor(res.getColor(usageColor));
+        final DataUsageGraph graph = (DataUsageGraph) findViewById(R.id.usage_graph);
+        graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
+        final TextView carrier = (TextView) findViewById(R.id.usage_carrier_text);
+        carrier.setText(info.carrier);
+        final TextView period = (TextView) findViewById(R.id.usage_period_text);
+        period.setText(info.period);
+        final TextView infoTop = (TextView) findViewById(R.id.usage_info_top_text);
+        infoTop.setVisibility(top != null ? View.VISIBLE : View.GONE);
+        infoTop.setText(top);
+        final TextView infoBottom = (TextView) findViewById(R.id.usage_info_bottom_text);
+        infoBottom.setVisibility(bottom != null ? View.VISIBLE : View.GONE);
+        infoBottom.setText(bottom);
+    }
+
+    private String formatBytes(long bytes) {
+        final long b = Math.abs(bytes);
+        double val;
+        String suffix;
+        if (b > 100 * MB) {
+            val = b / GB;
+            suffix = "GB";
+        } else if (b > 100 * KB) {
+            val = b / MB;
+            suffix = "MB";
+        } else {
+            val = b / KB;
+            suffix = "KB";
+        }
+        return FORMAT.format(val * (bytes < 0 ? -1 : 1)) + " " + suffix;
+    }
+}
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 7ac6644..46d8a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -54,12 +54,7 @@
     @Override
     protected void handleClick() {
         final boolean wasEnabled = (Boolean) mState.value;
-        final boolean changed = mController.setLocationEnabled(!wasEnabled);
-        if (!wasEnabled && changed) {
-            // If we've successfully switched from location off to on, close the
-            // notifications tray to show the network location provider consent dialog.
-            mHost.collapsePanels();
-        }
+        mController.setLocationEnabled(!wasEnabled);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index a56b7a7..c55cbccb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -17,15 +17,18 @@
 package com.android.systemui.qs.tiles;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.UserAvatarView;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -107,6 +110,12 @@
     }
 
     @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        FontSizeUtils.updateFontSize(mName, R.dimen.qs_detail_item_secondary_text_size);
+    }
+
+    @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
         updateTypeface();
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index 25a62ae..bdb0ad3 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -191,6 +191,11 @@
         return true;
     }
 
+    @Override
+    public boolean isAntiFalsingNeeded() {
+        return false;
+    }
+
     public void dismissChild(View v) {
         mSwipeHelper.dismissChild(v, 0);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index e8e9d52..47c096f 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -199,6 +199,11 @@
         return true;
     }
 
+    @Override
+    public boolean isAntiFalsingNeeded() {
+        return false;
+    }
+
     public void dismissChild(View v) {
         mSwipeHelper.dismissChild(v, 0);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 0b36bdbd..ec39d77 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -22,7 +22,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -36,7 +35,6 @@
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.recents.misc.Console;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskGrouping;
@@ -74,6 +72,7 @@
     static RecentsComponent.Callbacks sRecentsComponentCallbacks;
 
     Context mContext;
+    LayoutInflater mInflater;
     SystemServicesProxy mSystemServicesProxy;
     Handler mHandler;
     boolean mBootCompleted;
@@ -99,32 +98,21 @@
     long mLastToggleTime;
 
     public AlternateRecentsComponent(Context context) {
-        Resources res = context.getResources();
+        RecentsTaskLoader.initialize(context);
+        mInflater = LayoutInflater.from(context);
         mContext = context;
         mSystemServicesProxy = new SystemServicesProxy(context);
         mHandler = new Handler();
-        mConfig = RecentsConfiguration.reinitialize(context, mSystemServicesProxy);
-        mWindowRect = mSystemServicesProxy.getWindowRect();
         mTaskStackBounds = new Rect();
-        mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-        mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
-        mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
-        mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
-                mNavBarWidth, mTaskStackBounds);
-        if (mConfig.isLandscape && mConfig.transposeRecentsLayoutWithOrientation) {
-            mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
-        } else {
-            mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
-        }
     }
 
-    public void onStart() {
-        // Initialize some static datastructures
-        TaskStackViewLayoutAlgorithm.initializeCurve();
-        reloadHeaderBarLayout();
-    }
+    public void onStart() {}
 
     public void onBootCompleted() {
+        // Initialize some static datastructures
+        TaskStackViewLayoutAlgorithm.initializeCurve();
+        // Load the header bar layout
+        reloadHeaderBarLayout();
         mBootCompleted = true;
     }
 
@@ -176,8 +164,9 @@
     }
 
     void showRelativeAffiliatedTask(boolean showNextTask) {
-        TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy,
-                Integer.MAX_VALUE, mContext.getResources());
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
+                -1, -1, false, null, null);
         // Return early if there are no tasks
         if (stack.getTaskCount() == 0) return;
 
@@ -235,9 +224,19 @@
     }
 
     public void onConfigurationChanged(Configuration newConfig) {
+        reloadHeaderBarLayout();
+        sLastScreenshot = null;
+    }
+
+    /** Prepares the header bar layout. */
+    void reloadHeaderBarLayout() {
+        Resources res = mContext.getResources();
+        mWindowRect = mSystemServicesProxy.getWindowRect();
+        mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+        mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
+        mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
         mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy);
         mConfig.updateOnConfigurationChange();
-        mWindowRect = mSystemServicesProxy.getWindowRect();
         mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
                 mNavBarWidth, mTaskStackBounds);
         if (mConfig.isLandscape && mConfig.transposeRecentsLayoutWithOrientation) {
@@ -245,14 +244,8 @@
         } else {
             mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
         }
-        sLastScreenshot = null;
-        reloadHeaderBarLayout();
-    }
 
-    /** Prepares the header bar layout. */
-    void reloadHeaderBarLayout() {
         // Inflate the header bar layout so that we can rebind and draw it for the transition
-        Resources res = mContext.getResources();
         TaskStack stack = new TaskStack();
         mDummyStackView = new TaskStackView(mContext, stack);
         TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
@@ -261,8 +254,7 @@
         algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
         Rect taskViewSize = algo.getUntransformedTaskViewSize();
         int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
-        LayoutInflater inflater = LayoutInflater.from(mContext);
-        mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, null,
+        mHeaderBar = (TaskViewHeader) mInflater.inflate(R.layout.recents_task_view_header, null,
                 false);
         mHeaderBar.measure(
                 View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY),
@@ -385,16 +377,8 @@
                 toTask);
         if (toTransform != null && toTask.key != null) {
             Rect toTaskRect = toTransform.rect;
-            ActivityInfo info = mSystemServicesProxy.getActivityInfo(
-                    toTask.key.baseIntent.getComponent(), toTask.key.userId);
-            if (toTask.activityIcon == null) {
-                toTask.activityIcon = mSystemServicesProxy.getActivityIcon(info,
-                        toTask.key.userId);
-            }
-            if (toTask.activityLabel == null) {
-                toTask.activityLabel = mSystemServicesProxy.getActivityLabel(info);
-            }
 
+            // XXX: Reduce the memory usage the to the task bar height
             Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
                     Bitmap.Config.ARGB_8888);
             if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
@@ -420,16 +404,13 @@
     TaskViewTransform getThumbnailTransitionTransform(int runningTaskId, boolean isTopTaskHome,
                                                       Task runningTaskOut) {
         // Get the stack of tasks that we are animating into
-        TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1,
-                mContext.getResources());
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
+                runningTaskId, -1, false, null, null);
         if (stack.getTaskCount() == 0) {
             return null;
         }
 
-        // Get the stack
-        mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
-        mDummyStackView.getScroller().setStackScrollToInitialState();
-
         // Find the running task in the TaskStack
         Task task = null;
         ArrayList<Task> tasks = stack.getTasks();
@@ -451,6 +432,8 @@
         }
 
         // Get the transform for the running task
+        mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
+        mDummyStackView.getScroller().setStackScrollToInitialState();
         mTmpTransform = mDummyStackView.getStackAlgorithm().getStackTransform(task,
                 mDummyStackView.getScroller().getStackScroll(), mTmpTransform, null);
         return mTmpTransform;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index a5b845d..2f9715f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -343,7 +343,6 @@
         super.onCreate(savedInstanceState);
 
         // Initialize the loader and the configuration
-        RecentsTaskLoader.initialize(this);
         mConfig = RecentsConfiguration.reinitialize(this,
                 RecentsTaskLoader.getInstance().getSystemServicesProxy());
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 9803687..5d8181c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -67,9 +67,11 @@
     public int searchBarSpaceHeightPx;
 
     /** Task stack */
+    public int taskStackScrollDuration;
     public int taskStackMaxDim;
     public int taskStackTopPaddingPx;
     public float taskStackWidthPaddingPct;
+    public float taskStackOverscrollPct;
 
     /** Task view animation and styles */
     public int taskViewEnterFromHomeDuration;
@@ -195,9 +197,14 @@
         searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
 
         // Task stack
+        taskStackScrollDuration =
+                res.getInteger(R.integer.recents_animate_task_stack_scroll_duration);
         TypedValue widthPaddingPctValue = new TypedValue();
         res.getValue(R.dimen.recents_stack_width_padding_percentage, widthPaddingPctValue, true);
         taskStackWidthPaddingPct = widthPaddingPctValue.getFloat();
+        TypedValue stackOverscrollPctValue = new TypedValue();
+        res.getValue(R.dimen.recents_stack_overscroll_percentage, stackOverscrollPctValue, true);
+        taskStackOverscrollPct = stackOverscrollPctValue.getFloat();
         taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
         taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
index 31011ae..60e89bf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recents.model;
 
-import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Looper;
@@ -36,7 +35,7 @@
     }
 
     PackageCallbacks mCb;
-    List<ActivityManager.RecentTaskInfo> mTasks;
+    List<Task.TaskKey> mTasks;
     SystemServicesProxy mSystemServicesProxy;
 
     /** Registers the broadcast receivers with the specified callbacks. */
@@ -64,7 +63,7 @@
     }
 
     /** Sets the list of tasks to match against package broadcast changes. */
-    void setTasks(List<ActivityManager.RecentTaskInfo> tasks) {
+    void setTasks(List<Task.TaskKey> tasks) {
         mTasks = tasks;
     }
 
@@ -75,7 +74,7 @@
         // Identify all the tasks that should be removed as a result of the package being removed.
         // Using a set to ensure that we callback once per unique component.
         HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
-        for (ActivityManager.RecentTaskInfo t : mTasks) {
+        for (Task.TaskKey t : mTasks) {
             ComponentName cn = t.baseIntent.getComponent();
             if (cn.getPackageName().equals(packageName)) {
                 componentsToRemove.add(cn);
@@ -99,7 +98,7 @@
         // Using a set to ensure that we callback once per unique component.
         HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
         HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
-        for (ActivityManager.RecentTaskInfo t : mTasks) {
+        for (Task.TaskKey t : mTasks) {
             ComponentName cn = t.baseIntent.getComponent();
             if (cn.getPackageName().equals(packageName)) {
                 if (componentsKnownToExist.contains(cn)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index b93c126..f7ad35b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -18,7 +18,6 @@
 
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
@@ -28,6 +27,8 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.UserHandle;
+import android.util.Log;
+
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -35,11 +36,16 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
 
+/** Handle to an ActivityInfo */
+class ActivityInfoHandle {
+    ActivityInfo info;
+}
+
 /** A bitmap load queue */
 class TaskResourceLoadQueue {
     ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>();
@@ -227,10 +233,11 @@
 /* Recents task loader
  * NOTE: We should not hold any references to a Context from a static instance */
 public class RecentsTaskLoader {
+    private static final String TAG = "RecentsTaskLoader";
+
     static RecentsTaskLoader sInstance;
 
     SystemServicesProxy mSystemServicesProxy;
-    DrawableLruCache mTaskDescriptionIconCache;
     DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
     StringLruCache mActivityLabelCache;
@@ -274,7 +281,6 @@
         mSystemServicesProxy = new SystemServicesProxy(context);
         mPackageMonitor = new RecentsPackageMonitor();
         mLoadQueue = new TaskResourceLoadQueue();
-        mTaskDescriptionIconCache = new DrawableLruCache(iconCacheSize);
         mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
         mActivityLabelCache = new StringLruCache(100);
@@ -301,103 +307,162 @@
     }
 
     /** Gets the list of recent tasks, ordered from back to front. */
-    private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp,
-            int numTasks) {
-        // Set a default number of tasks to query if none is provided
-        if (numTasks < 0) {
-            RecentsConfiguration config = RecentsConfiguration.getInstance();
-            numTasks = config.maxNumTasksToLoad;
-        }
+    private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp) {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
         List<ActivityManager.RecentTaskInfo> tasks =
-                ssp.getRecentTasks(numTasks, UserHandle.CURRENT.getIdentifier());
+                ssp.getRecentTasks(config.maxNumTasksToLoad,
+                        UserHandle.CURRENT.getIdentifier());
         Collections.reverse(tasks);
         return tasks;
     }
 
+    /** Returns the activity icon using as many cached values as we can. */
+    public Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey,
+             ActivityManager.TaskDescription td, SystemServicesProxy ssp,
+             Resources res, ActivityInfoHandle infoHandle, boolean preloadTask) {
+        // Return the cached activity icon if it exists
+        Drawable icon = mApplicationIconCache.getAndInvalidateIfModified(taskKey);
+        if (icon != null) {
+            return icon;
+        }
+        // Return the task description icon if it exists
+        if (td != null && td.getIcon() != null) {
+            icon = ssp.getBadgedIcon(new BitmapDrawable(res, td.getIcon()), taskKey.userId);
+            mApplicationIconCache.put(taskKey, icon);
+            return icon;
+        }
+        // If we are preloading this task, continue to load the activity icon
+        if (preloadTask) {
+            // All short paths failed, load the icon from the activity info and cache it
+            if (infoHandle.info == null) {
+                infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(),
+                        taskKey.userId);
+            }
+            if (infoHandle.info != null) {
+                icon = ssp.getActivityIcon(infoHandle.info, taskKey.userId);
+                if (icon != null) {
+                    mApplicationIconCache.put(taskKey, icon);
+                    return icon;
+                }
+            }
+        }
+        // If we couldn't load any icon, return null
+        return null;
+    }
+
+    /** Returns the activity label using as many cached values as we can. */
+    public String getAndUpdateActivityLabel(Task.TaskKey taskKey,
+            ActivityManager.TaskDescription td, SystemServicesProxy ssp,
+            ActivityInfoHandle infoHandle) {
+        // Return the task description label if it exists
+        if (td != null && td.getLabel() != null) {
+            return td.getLabel();
+        }
+        // Return the cached activity label if it exists
+        String label = mActivityLabelCache.getAndInvalidateIfModified(taskKey);
+        if (label != null) {
+            return label;
+        }
+        // All short paths failed, load the label from the activity info and cache it
+        if (infoHandle.info == null) {
+            infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(),
+                    taskKey.userId);
+        }
+        if (infoHandle.info != null) {
+            label = ssp.getActivityLabel(infoHandle.info);
+            mActivityLabelCache.put(taskKey, label);
+        } else {
+            Log.w(TAG, "Missing ActivityInfo for " + taskKey.baseIntent.getComponent()
+                    + " u=" + taskKey.userId);
+        }
+        return label;
+    }
+
+    /** Returns the activity's primary color. */
+    public int getActivityPrimaryColor(ActivityManager.TaskDescription td,
+            RecentsConfiguration config) {
+        if (td != null && td.getPrimaryColor() != 0) {
+            return td.getPrimaryColor();
+        }
+        return config.taskBarViewDefaultBackgroundColor;
+    }
+
     /** Reload the set of recent tasks */
     public SpaceNode reload(Context context, int preloadCount) {
-        RecentsConfiguration config = RecentsConfiguration.getInstance();
-        Resources res = context.getResources();
-        LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>();
-        ArrayList<Task> tasksToAdd = new ArrayList<Task>();
-        TaskStack stack = new TaskStack();
+        ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
+        ArrayList<Task> tasksToLoad = new ArrayList<Task>();
+        TaskStack stack = getTaskStack(mSystemServicesProxy, context.getResources(),
+                -1, preloadCount, true, taskKeys, tasksToLoad);
         SpaceNode root = new SpaceNode();
         root.setStack(stack);
 
-        // Get the recent tasks
-        SystemServicesProxy ssp = mSystemServicesProxy;
-        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, -1);
+        // Start the task loader and add all the tasks we need to load
+        mLoader.start(context);
+        mLoadQueue.addTasks(tasksToLoad);
 
-        // From back to front, add each task to the task stack
+        // Update the package monitor with the list of packages to listen for
+        mPackageMonitor.setTasks(taskKeys);
+
+        return root;
+    }
+
+    /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
+    public TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
+            int preloadTaskId, int preloadTaskCount,
+            boolean loadTaskThumbnails, List<Task.TaskKey> taskKeysOut,
+            List<Task> tasksToLoadOut) {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp);
+        HashMap<Task.ComponentNameKey, ActivityInfoHandle> activityInfoCache =
+                new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
+        ArrayList<Task> tasksToAdd = new ArrayList<Task>();
+        TaskStack stack = new TaskStack();
+
         int taskCount = tasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = tasks.get(i);
+
+            // Compose the task key
             Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
                     t.firstActiveTime, t.lastActiveTime);
-            ComponentName cn = t.baseIntent.getComponent();
-            ActivityInfo info = null;
 
-            ActivityManager.TaskDescription av = t.taskDescription;
-            String activityLabel  = null;
-            Drawable activityIcon = mDefaultApplicationIcon;
-            int activityColor = config.taskBarViewDefaultBackgroundColor;
-            boolean loadedActivityIcon = false;
-            if (av != null) {
-                activityLabel = av.getLabel();
-                activityIcon = mTaskDescriptionIconCache.getAndInvalidateIfModified(taskKey);
-                if (activityIcon == null) {
-                    activityIcon = (av.getIcon() != null) ?
-                        ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null;
-                    if (activityIcon != null) {
-                        mTaskDescriptionIconCache.put(taskKey, activityIcon);
-                    }
-                }
-                if (av.getPrimaryColor() != 0) {
-                    activityColor = av.getPrimaryColor();
-                }
-                loadedActivityIcon = (activityIcon != null);
-            }
-            // If there is no activity label, then try and read it from the label cache before
-            // loading it from the system
-            if (activityLabel == null) {
-                activityLabel = mActivityLabelCache.getAndInvalidateIfModified(taskKey);
-                if (activityLabel == null) {
-                    if (info == null) {
-                        info = ssp.getActivityInfo(cn, t.userId);
-                    }
-                    activityLabel = ssp.getActivityLabel(info);
-                    mActivityLabelCache.put(taskKey, activityLabel);
-                }
+            // Get an existing activity info handle if possible
+            Task.ComponentNameKey cnKey = taskKey.getComponentNameKey();
+            ActivityInfoHandle infoHandle;
+            boolean hasCachedActivityInfo = false;
+            if (activityInfoCache.containsKey(cnKey)) {
+                infoHandle = activityInfoCache.get(cnKey);
+                hasCachedActivityInfo = true;
+            } else {
+                infoHandle = new ActivityInfoHandle();
             }
 
-            // Create a new task
+            // Determine whether to preload this task
+            boolean preloadTask = false;
+            if (preloadTaskId > 0) {
+                preloadTask = (t.id == preloadTaskId);
+            } else if (preloadTaskCount > 0) {
+                preloadTask = (i >= (taskCount - preloadTaskCount));
+            }
+
+            // Load the label, icon, and color
+            String activityLabel  = getAndUpdateActivityLabel(taskKey, t.taskDescription,
+                    ssp, infoHandle);
+            Drawable activityIcon = getAndUpdateActivityIcon(taskKey, t.taskDescription,
+                    ssp, res, infoHandle, preloadTask);
+            int activityColor = getActivityPrimaryColor(t.taskDescription, config);
+
+            // Update the activity info cache
+            if (!hasCachedActivityInfo && infoHandle.info != null) {
+                activityInfoCache.put(cnKey, infoHandle);
+            }
+
+            // Add the task to the stack
             Task task = new Task(taskKey, (t.id > -1), t.affiliatedTaskId, t.affiliatedTaskColor,
                     activityLabel, activityIcon, activityColor, (i == (taskCount - 1)),
                     config.lockToAppEnabled);
 
-            // Preload the specified number of apps
-            if (i >= (taskCount - preloadCount)) {
-                // Load the icon from the cache if possible (only if we don't have an activity icon)
-                if (!loadedActivityIcon) {
-                    task.applicationIcon =
-                            mApplicationIconCache.getAndInvalidateIfModified(taskKey);
-                    if (task.applicationIcon == null) {
-                        // Load the icon from the system
-                        if (info == null) {
-                            info = ssp.getActivityInfo(cn, t.userId);
-                        }
-                        task.applicationIcon = ssp.getActivityIcon(info, taskKey.userId);
-                        if (task.applicationIcon != null) {
-                            mApplicationIconCache.put(taskKey, task.applicationIcon);
-                        }
-                    }
-                    if (task.applicationIcon == null) {
-                        // Either the task has changed since the last active time, or it was not
-                        // previously cached, so try and load the task anew.
-                        tasksToLoad.add(task);
-                    }
-                }
-
+            if (preloadTask && loadTaskThumbnails) {
                 // Load the thumbnail from the cache if possible
                 task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey);
                 if (task.thumbnail == null) {
@@ -408,54 +473,20 @@
                         mThumbnailCache.put(taskKey, task.thumbnail);
                     }
                 }
-                if (task.thumbnail == null) {
+                if (task.thumbnail == null && tasksToLoadOut != null) {
                     // Either the task has changed since the last active time, or it was not
                     // previously cached, so try and load the task anew.
-                    tasksToLoad.add(task);
+                    tasksToLoadOut.add(task);
                 }
             }
 
+            // Add to the list of task keys
+            if (taskKeysOut != null) {
+                taskKeysOut.add(taskKey);
+            }
             // Add the task to the stack
             tasksToAdd.add(task);
         }
-
-        // Simulate the groupings that we describe
-        stack.setTasks(tasksToAdd);
-        stack.createAffiliatedGroupings(config);
-
-        // Start the task loader and add all the tasks we need to load
-        mLoader.start(context);
-        mLoadQueue.addTasks(tasksToLoad);
-
-        // Update the package monitor with the list of packages to listen for
-        mPackageMonitor.setTasks(tasks);
-
-        return root;
-    }
-
-    /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
-    public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks,
-            Resources resources) {
-        RecentsConfiguration config = RecentsConfiguration.getInstance();
-        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, numTasks);
-        ArrayList<Task> tasksToAdd = new ArrayList<Task>();
-        TaskStack stack = new TaskStack();
-
-        int taskCount = tasks.size();
-        for (int i = 0; i < taskCount; i++) {
-            ActivityManager.RecentTaskInfo t = tasks.get(i);
-            ActivityManager.TaskDescription av = t.taskDescription;
-
-            BitmapDrawable icon = null;
-            if (av.getIcon() != null) {
-                icon = new BitmapDrawable(resources, av.getIcon());
-            }
-            Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
-                    t.firstActiveTime, t.lastActiveTime);
-            tasksToAdd.add(new Task(taskKey, true, t.affiliatedTaskId, t.affiliatedTaskColor,
-                    av.getLabel(), icon, av.getPrimaryColor(), (i == (taskCount - 1)),
-                    config.lockToAppEnabled));
-        }
         stack.setTasks(tasksToAdd);
         stack.createAffiliatedGroupings(config);
         return stack;
@@ -525,21 +556,18 @@
                 // We are leaving recents, so trim the data a bit
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
                 mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2);
-                mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 2);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
             case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                 // We are going to be low on memory
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
                 mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4);
-                mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 4);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                 // We are low on memory, so release everything
                 mThumbnailCache.evictAll();
                 mApplicationIconCache.evictAll();
-                mTaskDescriptionIconCache.evictAll();
                 // The cache is small, only clear the label cache when we are critical
                 mActivityLabelCache.evictAll();
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 977db60..406e03f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -16,12 +16,15 @@
 
 package com.android.systemui.recents.model;
 
+import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import com.android.systemui.recents.misc.Utilities;
 
+import java.util.Objects;
+
 
 /**
  * A task represents the top most task in the system's task stack.
@@ -35,8 +38,35 @@
         public void onTaskDataUnloaded();
     }
 
+    /** The ComponentNameKey represents the unique primary key for a component
+     * belonging to a specified user. */
+    public static class ComponentNameKey {
+        final ComponentName component;
+        final int userId;
+
+        public ComponentNameKey(ComponentName cn, int user) {
+            component = cn;
+            userId = user;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(component, userId);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof ComponentNameKey)) {
+                return false;
+            }
+            return component.equals(((ComponentNameKey) o).component) &&
+                    userId == ((ComponentNameKey) o).userId;
+        }
+    }
+
     /* The Task Key represents the unique primary key for the task */
     public static class TaskKey {
+        final ComponentNameKey mComponentNameKey;
         public final int id;
         public final Intent baseIntent;
         public final int userId;
@@ -44,6 +74,7 @@
         public long lastActiveTime;
 
         public TaskKey(int id, Intent intent, int userId, long firstActiveTime, long lastActiveTime) {
+            mComponentNameKey = new ComponentNameKey(intent.getComponent(), userId);
             this.id = id;
             this.baseIntent = intent;
             this.userId = userId;
@@ -51,6 +82,11 @@
             this.lastActiveTime = lastActiveTime;
         }
 
+        /** Returns the component name key for this task. */
+        public ComponentNameKey getComponentNameKey() {
+            return mComponentNameKey;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (!(o instanceof TaskKey)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 34f73c6..d6889d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -33,6 +33,8 @@
     Rect mClipRect = new Rect();
     Rect mOutlineClipRect = new Rect();
     int mCornerRadius;
+    float mAlpha = 1f;
+    final float mMinAlpha = 0.25f;
 
     ObjectAnimator mClipTopAnimator;
     ObjectAnimator mClipRightAnimator;
@@ -51,6 +53,7 @@
 
     @Override
     public void getOutline(View view, Outline outline) {
+        outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
         outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
                 Math.max(mClipRect.top, mOutlineClipRect.top),
                 mSourceView.getMeasuredWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
@@ -58,6 +61,14 @@
                 mCornerRadius);
     }
 
+    /** Sets the view outline alpha. */
+    void setAlpha(float alpha) {
+        if (Float.compare(alpha, mAlpha) != 0) {
+            mAlpha = alpha;
+            mSourceView.invalidateOutline();
+        }
+    }
+
     /** Animates the top clip. */
     void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) {
         if (mClipTopAnimator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 47fda5b..1ac3bc3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -477,10 +477,10 @@
             if (!task.group.isFrontMostTask(task)) {
                 // For affiliated tasks that are behind other tasks, we must animate the front cards
                 // out of view before starting the task transition
-                stackView.startLaunchTaskAnimation(tv, launchRunnable);
+                stackView.startLaunchTaskAnimation(tv, launchRunnable, lockToTask);
             } else {
                 // Otherwise, we can start the task transition immediately
-                stackView.startLaunchTaskAnimation(tv, null);
+                stackView.startLaunchTaskAnimation(tv, null, lockToTask);
                 postDelayed(launchRunnable, 17);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index e0298ab..fa44551e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -28,6 +28,7 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.animation.LinearInterpolator;
+import com.android.systemui.recents.RecentsConfiguration;
 
 /**
  * This class facilitates swipe to dismiss. It defines an interface to be implemented by the
@@ -50,7 +51,7 @@
     private int DEFAULT_ESCAPE_ANIMATION_DURATION = 75; // ms
     private int MAX_ESCAPE_ANIMATION_DURATION = 150; // ms
     private int MAX_DISMISS_VELOCITY = 2000; // dp/sec
-    private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 150; // ms
+    private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; // ms
 
     public static float ALPHA_FADE_START = 0.15f; // fraction of thumbnail width
                                                  // where fade starts
@@ -265,6 +266,7 @@
         ValueAnimator anim = createTranslationAnimation(view, 0);
         int duration = SNAP_ANIM_LEN;
         anim.setDuration(duration);
+        anim.setInterpolator(RecentsConfiguration.getInstance().linearOutSlowInInterpolator);
         anim.addUpdateListener(new AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 861011f..dbed136 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -105,7 +105,7 @@
         mFilterAlgorithm = new TaskStackViewFilterAlgorithm(mConfig, this, mViewPool);
         mStackScroller = new TaskStackViewScroller(context, mConfig, mLayoutAlgorithm);
         mStackScroller.setCallbacks(this);
-        mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
+        mTouchHandler = new TaskStackViewTouchHandler(context, this, mConfig, mStackScroller);
         mUIDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() {
             @Override
             public void run() {
@@ -647,17 +647,17 @@
     }
 
     /** Animates a task view in this stack as it launches. */
-    public void startLaunchTaskAnimation(TaskView tv, final Runnable r) {
+    public void startLaunchTaskAnimation(TaskView tv, Runnable r, boolean lockToTask) {
         Task launchTargetTask = tv.getTask();
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             TaskView t = (TaskView) getChildAt(i);
             if (t == tv) {
-                t.startLaunchTaskAnimation(r, true, true);
+                t.startLaunchTaskAnimation(r, true, true, lockToTask);
             } else {
                 boolean occludesLaunchTarget = launchTargetTask.group.isTaskAboveTask(t.getTask(),
                         launchTargetTask);
-                t.startLaunchTaskAnimation(null, false, occludesLaunchTarget);
+                t.startLaunchTaskAnimation(null, false, occludesLaunchTarget, lockToTask);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 2c0dc44..5852b88 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -133,12 +133,8 @@
         stopBoundScrollAnimation();
 
         mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll);
-        mScrollAnimator.setDuration(200);
-        // We would have to project the difference into the screen coords, and then use that as the
-        // duration
-//        mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
-//                curScroll, 250));
-        mScrollAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+        mScrollAnimator.setDuration(mConfig.taskStackScrollDuration);
+        mScrollAnimator.setInterpolator(mConfig.linearOutSlowInInterpolator);
         mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 374a27f..8f9b4c2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -23,11 +23,13 @@
 import android.view.ViewConfiguration;
 import android.view.ViewParent;
 import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsConfiguration;
 
 /* Handles touch events for a TaskStackView. */
 class TaskStackViewTouchHandler implements SwipeHelper.Callback {
     static int INACTIVE_POINTER_ID = -1;
 
+    RecentsConfiguration mConfig;
     TaskStackView mSv;
     TaskStackViewScroller mScroller;
     VelocityTracker mVelocityTracker;
@@ -52,7 +54,8 @@
     SwipeHelper mSwipeHelper;
     boolean mInterceptedBySwipeHelper;
 
-    public TaskStackViewTouchHandler(Context context, TaskStackView sv, TaskStackViewScroller scroller) {
+    public TaskStackViewTouchHandler(Context context, TaskStackView sv,
+            RecentsConfiguration config, TaskStackViewScroller scroller) {
         ViewConfiguration configuration = ViewConfiguration.get(context);
         mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
@@ -60,6 +63,7 @@
         mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
         mSv = sv;
         mScroller = scroller;
+        mConfig = config;
 
         float densityScale = context.getResources().getDisplayMetrics().density;
         mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
@@ -258,7 +262,7 @@
                     if (Float.compare(overScrollAmount, 0f) != 0) {
                         // Bound the overscroll to a fixed amount, and inversely scale the y-movement
                         // relative to how close we are to the max overscroll
-                        float maxOverScroll = 0.25f;
+                        float maxOverScroll = mConfig.taskStackOverscrollPct;
                         deltaP *= (1f - (Math.min(maxOverScroll, overScrollAmount)
                                 / maxOverScroll));
                     }
@@ -280,7 +284,6 @@
                 velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                 int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
                 if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
-                    // XXX: Should this be calculated as a percentage of a curve?
                     int overscrollRange = (int) (Math.min(1f,
                             Math.abs((float) velocity / mMaximumVelocity)) *
                             Constants.Values.TaskStackView.TaskStackOverscrollRange);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index dfbcce1..eecc170 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -471,7 +471,7 @@
 
     /** Animates this task view as it exits recents */
     void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask,
-            boolean occludesLaunchTarget) {
+            boolean occludesLaunchTarget, boolean lockToTask) {
         if (isLaunchingTask) {
             // Disable the thumbnail clip
             mThumbnailView.disableTaskBarClip();
@@ -487,11 +487,14 @@
             }
 
             // Animate the action button away
-            float toScale = 0.9f;
+            if (!lockToTask) {
+                float toScale = 0.9f;
+                mActionButtonView.animate()
+                        .scaleX(toScale)
+                        .scaleY(toScale);
+            }
             mActionButtonView.animate()
                     .alpha(0f)
-                    .scaleX(toScale)
-                    .scaleY(toScale)
                     .setStartDelay(0)
                     .setDuration(mConfig.taskBarExitAnimDuration)
                     .setInterpolator(mConfig.fastOutLinearInInterpolator)
@@ -621,6 +624,7 @@
     /** Sets the current task progress. */
     public void setTaskProgress(float p) {
         mTaskProgress = p;
+        mViewBounds.setAlpha(p);
         updateDimFromTaskProgress();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index fef4a39..500bf45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -461,6 +461,8 @@
         if (mDrawingAppearAnimation) {
             startAppearAnimation(false /* isAppearing */, translationDirection,
                     0, duration, onFinishedRunnable);
+        } else if (onFinishedRunnable != null) {
+            onFinishedRunnable.run();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index df005a8..c8adf61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -276,7 +276,7 @@
                         // Wait for activity start.
                         return handled;
                     }
-                });
+                }, false /* afterKeyguardGone */);
                 return true;
             } else {
                 return super.onClickHandler(view, pendingIntent, fillInIntent);
@@ -526,8 +526,9 @@
     /**
      * Takes the necessary steps to prepare the status bar for starting an activity, then starts it.
      * @param action A dismiss action that is called if it's safe to start the activity.
+     * @param afterKeyguardGone Whether the action should be executed after the Keyguard is gone.
      */
-    protected void dismissKeyguardThenExecute(OnDismissAction action) {
+    protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
         action.onDismiss();
     }
 
@@ -581,9 +582,11 @@
 
     protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
             NotificationData.Entry entry) {
+        PackageManager pmUser = getPackageManagerForUser(
+                entry.notification.getUser().getIdentifier());
         int version = 0;
         try {
-            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
+            ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
             version = info.targetSdkVersion;
         } catch (NameNotFoundException ex) {
             Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
@@ -646,7 +649,7 @@
                 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
                 return true;
             }
-        });
+        }, false /* afterKeyguardGone */);
     }
 
     protected SwipeHelper.LongPressListener getNotificationLongClicker() {
@@ -1231,7 +1234,7 @@
             if (text != null) {
                 text.setText(R.string.notification_hidden_text);
                 text.setTextAppearance(mContext,
-                        R.style.TextAppearance_StatusBar_Material_EventContent_Parenthetical);
+                        R.style.TextAppearance_Material_Notification_Parenthetical);
             }
 
             int topPadding = Notification.Builder.calculateTopPadding(mContext,
@@ -1339,7 +1342,7 @@
 
                     return mIntent != null && mIntent.isActivity();
                 }
-            });
+            }, false /* afterKeyguardGone */);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 4a6bfa10..5878ae1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -163,6 +163,9 @@
 
     public void setPreviewView(View v) {
         mPreviewView = v;
+        if (mPreviewView != null) {
+            mPreviewView.setVisibility(INVISIBLE);
+        }
     }
 
     private void drawArrow(Canvas canvas) {
@@ -295,7 +298,7 @@
             duration = Math.min(duration, CIRCLE_DISAPPEAR_MAX_DURATION);
             animator.setDuration(duration);
             animator.start();
-            if (mPreviewView != null) {
+            if (mPreviewView != null && mPreviewView.getVisibility() == View.VISIBLE) {
                 mPreviewView.setVisibility(View.VISIBLE);
                 mPreviewClipper = ViewAnimationUtils.createCircularReveal(
                         mPreviewView, getLeft() + mCenterX, getTop() + mCenterY, mCircleRadius,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 548e7d2..8b4c2c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -202,7 +202,7 @@
     }
 
     public void setDark(boolean dark, boolean fade) {
-        if (mDark == dark) return;
+        if (mDark == dark || mContractedChild == null) return;
         mDark = dark;
         setImageViewDark(dark, fade, com.android.internal.R.id.right_icon);
         setImageViewDark(dark, fade, com.android.internal.R.id.icon);
@@ -211,6 +211,7 @@
     private void setImageViewDark(boolean dark, boolean fade, int imageViewId) {
         // TODO: implement fade
         final ImageView v = (ImageView) mContractedChild.findViewById(imageViewId);
+        if (v == null) return;
         final Drawable d = v.getBackground();
         if (dark) {
             v.setLayerType(LAYER_TYPE_HARDWARE, INVERT_PAINT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index fb13126..9da209a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -45,6 +45,7 @@
     private boolean mIsAirplaneMode = false;
     private int mAirplaneIconId = 0;
     private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
+    private boolean mRoaming;
 
     ViewGroup mWifiGroup, mMobileGroup;
     ImageView mWifi, mMobile, mMobileType, mAirplane;
@@ -106,12 +107,13 @@
 
     @Override
     public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
-            String contentDescription, String typeContentDescription) {
+            String contentDescription, String typeContentDescription, boolean roaming) {
         mMobileVisible = visible;
         mMobileStrengthId = strengthIcon;
         mMobileTypeId = typeIcon;
         mMobileDescription = contentDescription;
         mMobileTypeDescription = typeContentDescription;
+        mRoaming = roaming;
 
         apply();
     }
@@ -207,8 +209,7 @@
                     (mMobileVisible ? "VISIBLE" : "GONE"),
                     mMobileStrengthId, mMobileTypeId));
 
-        mMobileType.setVisibility(
-                !mWifiVisible ? View.VISIBLE : View.GONE);
+        mMobileType.setVisibility(!mWifiVisible || mRoaming ? View.VISIBLE : View.GONE);
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 23810f9..9dfbb27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,5 +24,5 @@
  * Keyguard.
  */
 public interface ActivityStarter {
-    public void startActivity(Intent intent, boolean dismissShade);
+    public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 936479b..c5d06b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -120,6 +120,11 @@
                         : 0;
                 updateSlot("speakerphone", null, iconId);
             }
+            String cast = args.getString("cast");
+            if (cast != null) {
+                int iconId = cast.equals("cast") ? R.drawable.stat_sys_cast : 0;
+                updateSlot("cast", null, iconId);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index c0b171a..f9da30f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -222,7 +222,8 @@
         ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
                 PackageManager.MATCH_DEFAULT_ONLY,
                 mLockPatternUtils.getCurrentUser());
-        boolean visible = !isCameraDisabledByDpm() && resolved != null;
+        boolean visible = !isCameraDisabledByDpm() && resolved != null
+                && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance);
         mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
     }
 
@@ -314,11 +315,15 @@
     public void launchCamera() {
         mFlashlightController.killFlashlight();
         Intent intent = getCameraIntent();
-        if (intent == SECURE_CAMERA_INTENT &&
-                !mPreviewInflater.wouldLaunchResolverActivity(intent)) {
+        boolean wouldLaunchResolverActivity = mPreviewInflater.wouldLaunchResolverActivity(intent);
+        if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         } else {
-            mActivityStarter.startActivity(intent, false /* dismissShade */);
+
+            // We need to delay starting the activity because ResolverActivity finishes itself if
+            // launched behind lockscreen.
+            mActivityStarter.startActivity(intent, false /* dismissShade */,
+                    wouldLaunchResolverActivity /* afterKeyguardGone */);
         }
     }
 
@@ -332,7 +337,8 @@
                 }
             });
         } else {
-            mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
+            mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */,
+                    mPreviewInflater.wouldLaunchResolverActivity(PHONE_INTENT));
         }
     }
 
@@ -374,21 +380,10 @@
         mLockIcon.setImageResource(iconRes);
         boolean trustManaged = mUnlockMethodCache.isTrustManaged();
         mTrustDrawable.setTrustManaged(trustManaged);
-
         updateLockIconClickability();
-        updateLockIconContentDescription(mUnlockMethodCache.isFaceUnlockRunning(),
-                mUnlockMethodCache.isMethodInsecure(), trustManaged);
     }
 
-    private void updateLockIconContentDescription(boolean faceUnlockRunning, boolean insecure,
-            boolean trustManaged) {
-        mLockIcon.setContentDescription(getResources().getString(
-                faceUnlockRunning ? R.string.accessibility_unlock_button_face_unlock_running
-                : insecure && !trustManaged ? R.string.accessibility_unlock_button_not_secured
-                : insecure ? R.string.accessibility_unlock_button_not_secured_trust_managed
-                : !trustManaged ? R.string.accessibility_unlock_button_secured
-                : R.string.accessibility_unlock_button_secured_trust_managed));
-    }
+
 
     public KeyguardAffordanceView getPhoneView() {
         return mPhoneImageView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 387abc3..d3c3f56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -160,6 +160,8 @@
 
     private boolean mQsScrimEnabled = true;
     private boolean mLastAnnouncementWasQuickSettings;
+    private boolean mQsTouchAboveFalsingThreshold;
+    private int mQsFalsingThreshold;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -230,6 +232,8 @@
         mClockPositionAlgorithm.loadDimens(getResources());
         mNotificationScrimWaitDistance =
                 getResources().getDimensionPixelSize(R.dimen.notification_scrim_wait_distance);
+        mQsFalsingThreshold = getResources().getDimensionPixelSize(
+                R.dimen.qs_falsing_threshold);
     }
 
     public void updateResources() {
@@ -526,6 +530,7 @@
     private void resetDownStates(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
             mOnlyAffordanceInThisMotion = false;
+            mQsTouchAboveFalsingThreshold = mQsFullyExpanded;
         }
     }
 
@@ -546,6 +551,9 @@
     }
 
     private boolean flingExpandsQs(float vel) {
+        if (!mQsTouchAboveFalsingThreshold && mStatusBarState == StatusBarState.KEYGUARD) {
+            return false;
+        }
         if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
             return getQsExpansionFraction() > 0.5f;
         } else {
@@ -690,6 +698,9 @@
             case MotionEvent.ACTION_MOVE:
                 final float h = y - mInitialTouchY;
                 setQsExpansion(h + mInitialHeightOnTouch);
+                if (h >= mQsFalsingThreshold) {
+                    mQsTouchAboveFalsingThreshold = true;
+                }
                 trackMovement(event);
                 break;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index b175fd5..e818d23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -68,6 +68,8 @@
     protected boolean mHintAnimationRunning;
     private boolean mOverExpandedBeforeFling;
     private float mOriginalIndicationY;
+    private boolean mTouchAboveFalsingThreshold;
+    private int mUnlockFalsingThreshold;
 
     private ValueAnimator mHeightAnimator;
     private ObjectAnimator mPeekAnimator;
@@ -183,6 +185,7 @@
         mTouchSlop = configuration.getScaledTouchSlop();
         mHintDistance = res.getDimension(R.dimen.hint_move_distance);
         mEdgeTapAreaWidth = res.getDimensionPixelSize(R.dimen.edge_tap_area_width);
+        mUnlockFalsingThreshold = res.getDimensionPixelSize(R.dimen.unlock_falsing_threshold);
     }
 
     private void trackMovement(MotionEvent event) {
@@ -234,6 +237,7 @@
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
                 mPeekTouching = mPanelClosedOnDown;
+                mTouchAboveFalsingThreshold = false;
                 if (mVelocityTracker == null) {
                     initVelocityTracker();
                 }
@@ -298,6 +302,9 @@
                     }
                     mJustPeeked = false;
                 }
+                if (-h >= mUnlockFalsingThreshold) {
+                    mTouchAboveFalsingThreshold = true;
+                }
                 if (!mJustPeeked && (!waitForTouchSlop || mTracking) && !isTrackingBlocked()) {
                     setExpandedHeightInternal(newHeight);
                 }
@@ -399,6 +406,7 @@
                 mPanelClosedOnDown = mExpandedHeight == 0.0f;
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
+                mTouchAboveFalsingThreshold = false;
                 initVelocityTracker();
                 trackMovement(event);
                 break;
@@ -471,6 +479,9 @@
      * @return whether a fling should expands the panel; contracts otherwise
      */
     protected boolean flingExpands(float vel, float vectorVel) {
+        if (!mTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded()) {
+            return true;
+        }
         if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
             return getExpandedFraction() > 0.5f;
         } else {
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 620d3ec..cd0fb6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -562,7 +562,7 @@
         addNavigationBar();
 
         // Lastly, call to the icon policy to install/update all the icons.
-        mIconPolicy = new PhoneStatusBarPolicy(mContext);
+        mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController);
         mSettingsObserver.onChange(false); // set up
 
         mHeadsUpObserver.onChange(true); // set up
@@ -686,6 +686,7 @@
         mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                 R.id.notification_stack_scroller);
         mStackScroller.setLongPressListener(getNotificationLongClicker());
+        mStackScroller.setPhoneStatusBar(this);
 
         mKeyguardIconOverflowContainer =
                 (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
@@ -2015,7 +2016,12 @@
                 .alpha(1f)
                 .setDuration(320)
                 .setInterpolator(ALPHA_IN)
-                .setStartDelay(50);
+                .setStartDelay(50)
+
+                // We need to clean up any pending end action from animateStatusBarHide if we call
+                // both hide and show in the same frame before the animation actually gets started.
+                // cancel() doesn't really remove the end action.
+                .withEndAction(null);
 
         // Synchronize the motion with the Keyguard fading if necessary.
         if (mKeyguardFadingAway) {
@@ -2033,8 +2039,8 @@
     }
 
     @Override
-    public void startActivity(Intent intent, boolean dismissShade) {
-        startActivityDismissingKeyguard(intent, false, dismissShade);
+    public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone) {
+        startActivityDismissingKeyguard(intent, false, dismissShade, afterKeyguardGone);
     }
 
     public ScrimController getScrimController() {
@@ -2053,6 +2059,12 @@
         return mNotificationPanel.isQsExpanded();
     }
 
+    public boolean isFalsingThresholdNeeded() {
+        boolean onKeyguard = getBarState() == StatusBarState.KEYGUARD;
+        boolean isMethodInSecure = mUnlockMethodCache.isMethodInsecure();
+        return onKeyguard && isMethodInSecure;
+    }
+
     @Override  // NotificationData.Environment
     public String getCurrentMediaNotificationKey() {
         return mMediaNotificationKey;
@@ -2917,7 +2929,7 @@
     }
 
     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
-            final boolean dismissShade) {
+            final boolean dismissShade, final boolean afterKeyguardGone) {
         if (onlyProvisioned && !isDeviceProvisioned()) return;
 
         final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
@@ -2927,7 +2939,7 @@
                 AsyncTask.execute(new Runnable() {
                     public void run() {
                         try {
-                            if (keyguardShowing) {
+                            if (keyguardShowing && !afterKeyguardGone) {
                                 ActivityManagerNative.getDefault()
                                         .keyguardWaitingForActivityDrawn();
                             }
@@ -2935,7 +2947,8 @@
                                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                             mContext.startActivityAsUser(
                                     intent, new UserHandle(UserHandle.USER_CURRENT));
-                            overrideActivityPendingAppTransition(keyguardShowing);
+                            overrideActivityPendingAppTransition(
+                                    keyguardShowing && !afterKeyguardGone);
                         } catch (RemoteException e) {
                         }
                     }
@@ -2945,7 +2958,7 @@
                 }
                 return true;
             }
-        });
+        }, afterKeyguardGone);
     }
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -3007,10 +3020,11 @@
     }
 
     @Override
-    protected void dismissKeyguardThenExecute(final OnDismissAction action) {
+    protected void dismissKeyguardThenExecute(final OnDismissAction action,
+            boolean afterKeyguardGone) {
         if (mStatusBarKeyguardViewManager.isShowing()) {
             if (UnlockMethodCache.getInstance(mContext).isMethodInsecure()
-                    && mNotificationPanel.isLaunchTransitionRunning()) {
+                    && mNotificationPanel.isLaunchTransitionRunning() && !afterKeyguardGone) {
                 action.onDismiss();
                 mNotificationPanel.setLaunchTransitionEndRunnable(new Runnable() {
                     @Override
@@ -3019,7 +3033,7 @@
                     }
                 });
             } else {
-                mStatusBarKeyguardViewManager.dismissWithAction(action);
+                mStatusBarKeyguardViewManager.dismissWithAction(action, afterKeyguardGone);
             }
         } else {
             action.onDismiss();
@@ -3258,7 +3272,8 @@
     }
 
     private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
-        startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
+        startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */,
+                false /* afterKeyguardGone */);
     }
 
     private static class FastColorDrawable extends Drawable {
@@ -3597,7 +3612,8 @@
     }
 
     public boolean onSpacePressed() {
-        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+        if (mScreenOn != null && mScreenOn
+                && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
             animateCollapsePanels(0 /* flags */, true /* force */);
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index bd52cd39..237b782 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -33,6 +33,8 @@
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastController.CastDevice;
 
 /**
  * This class contains all of the policy about which icons are installed in the status
@@ -46,6 +48,7 @@
     private static final boolean SHOW_SYNC_ICON = false;
 
     private static final String SLOT_SYNC_ACTIVE = "sync_active";
+    private static final String SLOT_CAST = "cast";
     private static final String SLOT_BLUETOOTH = "bluetooth";
     private static final String SLOT_TTY = "tty";
     private static final String SLOT_ZEN = "zen";
@@ -56,6 +59,7 @@
     private final Context mContext;
     private final StatusBarManager mService;
     private final Handler mHandler = new Handler();
+    private final CastController mCast;
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
@@ -98,8 +102,9 @@
         }
     };
 
-    public PhoneStatusBarPolicy(Context context) {
+    public PhoneStatusBarPolicy(Context context, CastController cast) {
         mContext = context;
+        mCast = cast;
         mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
 
         // listen for broadcasts
@@ -151,6 +156,11 @@
         mService.setIcon(SLOT_VOLUME, R.drawable.stat_sys_ringer_vibrate, 0, null);
         mService.setIconVisibility(SLOT_VOLUME, false);
         updateVolumeZen();
+
+        // cast
+        mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null);
+        mService.setIconVisibility(SLOT_CAST, false);
+        mCast.addCallback(mCastCallback);
     }
 
     public void setZenMode(int zen) {
@@ -287,4 +297,28 @@
             mService.setIconVisibility(SLOT_TTY, false);
         }
     }
+
+    private void updateCast() {
+        boolean isCasting = false;
+        for (CastDevice device : mCast.getCastDevices()) {
+            if (device.state == CastDevice.STATE_CONNECTING
+                    || device.state == CastDevice.STATE_CONNECTED) {
+                isCasting = true;
+                break;
+            }
+        }
+        if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
+        if (isCasting) {
+            mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0,
+                    mContext.getString(R.string.accessibility_casting));
+        }
+        mService.setIconVisibility(SLOT_CAST, isCasting);
+    }
+
+    private final CastController.Callback mCastCallback = new CastController.Callback() {
+        @Override
+        public void onCastDevicesChanged() {
+            updateCast();
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 729d459..2dc08d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -119,6 +119,7 @@
                 for (QSTile<?> tile : mTiles.values()) {
                     tile.userSwitch(newUserId);
                 }
+                mSecurity.onUserSwitched(newUserId);
                 mObserver.register();
             }
         };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 938d888..b6792f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -20,11 +20,14 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.MathUtils;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
@@ -36,6 +39,7 @@
 import android.widget.TextView;
 
 import com.android.keyguard.KeyguardStatusView;
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QSTile;
@@ -57,11 +61,11 @@
     private View mDateGroup;
     private View mClock;
     private TextView mTime;
-    private View mAmPm;
+    private TextView mAmPm;
     private MultiUserSwitch mMultiUserSwitch;
     private ImageView mMultiUserAvatar;
-    private View mDateCollapsed;
-    private View mDateExpanded;
+    private TextView mDateCollapsed;
+    private TextView mDateExpanded;
     private LinearLayout mSystemIcons;
     private View mStatusIcons;
     private View mSignalCluster;
@@ -70,7 +74,7 @@
     private TextView mQsDetailHeaderTitle;
     private Switch mQsDetailHeaderSwitch;
     private ImageView mQsDetailHeaderProgress;
-    private View mEmergencyCallsOnly;
+    private TextView mEmergencyCallsOnly;
     private TextView mBatteryLevel;
     private TextView mAlarmStatus;
 
@@ -129,11 +133,11 @@
         mDateGroup = findViewById(R.id.date_group);
         mClock = findViewById(R.id.clock);
         mTime = (TextView) findViewById(R.id.time_view);
-        mAmPm = findViewById(R.id.am_pm_view);
+        mAmPm = (TextView) findViewById(R.id.am_pm_view);
         mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
-        mDateCollapsed = findViewById(R.id.date_collapsed);
-        mDateExpanded = findViewById(R.id.date_expanded);
+        mDateCollapsed = (TextView) findViewById(R.id.date_collapsed);
+        mDateExpanded = (TextView) findViewById(R.id.date_expanded);
         mSettingsButton = findViewById(R.id.settings_button);
         mSettingsButton.setOnClickListener(this);
         mQsDetailHeader = findViewById(R.id.qs_detail_header);
@@ -141,7 +145,7 @@
         mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
         mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
         mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
-        mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only);
+        mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
         mBatteryLevel = (TextView) findViewById(R.id.battery_level);
         mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
         mAlarmStatus.setOnClickListener(this);
@@ -187,6 +191,39 @@
         mAlarmStatus.setX(mDateGroup.getLeft() + mDateCollapsed.getRight());
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        FontSizeUtils.updateFontSize(mBatteryLevel, R.dimen.battery_level_text_size);
+        FontSizeUtils.updateFontSize(mEmergencyCallsOnly,
+                R.dimen.qs_emergency_calls_only_text_size);
+        FontSizeUtils.updateFontSize(mDateCollapsed, R.dimen.qs_date_collapsed_size);
+        FontSizeUtils.updateFontSize(mDateExpanded, R.dimen.qs_date_collapsed_size);
+        FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
+        FontSizeUtils.updateFontSize(this, android.R.id.title, R.dimen.qs_detail_header_text_size);
+        FontSizeUtils.updateFontSize(this, android.R.id.toggle, R.dimen.qs_detail_header_text_size);
+        FontSizeUtils.updateFontSize(mAmPm, R.dimen.qs_time_collapsed_size);
+        FontSizeUtils.updateFontSize(this, R.id.empty_time_view, R.dimen.qs_time_expanded_size);
+
+        mClockCollapsedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size);
+        mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
+        mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize;
+
+        updateClockScale();
+        updateClockCollapsedMargin();
+    }
+
+    private void updateClockCollapsedMargin() {
+        Resources res = getResources();
+        int padding = res.getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin);
+        int largePadding = res.getDimensionPixelSize(
+                R.dimen.clock_collapsed_bottom_margin_large_text);
+        float largeFactor = (MathUtils.constrain(getResources().getConfiguration().fontScale, 1.0f,
+                FontSizeUtils.LARGE_TEXT_SCALE) - 1f) / (FontSizeUtils.LARGE_TEXT_SCALE - 1f);
+        mClockMarginBottomCollapsed = Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
+        requestLayout();
+    }
+
     private void requestCaptureValues() {
         mCaptureValues = true;
         requestLayout();
@@ -200,11 +237,9 @@
                 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
         mMultiUserCollapsedMargin =
                 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_collapsed_margin);
-
         mClockMarginBottomExpanded =
                 getResources().getDimensionPixelSize(R.dimen.clock_expanded_bottom_margin);
-        mClockMarginBottomCollapsed =
-                getResources().getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin);
+        updateClockCollapsedMargin();
         mMultiUserSwitchWidthCollapsed =
                 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_collapsed);
         mMultiUserSwitchWidthExpanded =
@@ -489,19 +524,20 @@
         } else if (v == mAlarmStatus && mNextAlarm != null) {
             PendingIntent showIntent = mNextAlarm.getShowIntent();
             if (showIntent != null && showIntent.isActivity()) {
-                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
+                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */,
+                        false /* afterKeyguardGone */);
             }
         }
     }
 
     private void startSettingsActivity() {
         mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
-                true /* dismissShade */);
+                true /* dismissShade */, false /* afterKeyguardGone */);
     }
 
     private void startBatteryActivity() {
         mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
-                true /* dismissShade */);
+                true /* dismissShade */, false /* afterKeyguardGone */);
     }
 
     public void setQSPanel(QSPanel qsp) {
@@ -732,7 +768,9 @@
             final boolean showingDetail = detail != null;
             transition(mClock, !showingDetail);
             transition(mDateGroup, !showingDetail);
-            transition(mAlarmStatus, !showingDetail);
+            if (mAlarmShowing) {
+                transition(mAlarmStatus, !showingDetail);
+            }
             transition(mQsDetailHeader, showingDetail);
             mShowingDetail = showingDetail;
             if (showingDetail) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 3338f6a..b4e2d57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -65,6 +65,7 @@
     private boolean mLastOccluded;
     private boolean mLastBouncerShowing;
     private boolean mLastBouncerDismissible;
+    private OnDismissAction mAfterKeyguardGoneAction;
 
     public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils) {
@@ -118,9 +119,14 @@
         updateStates();
     }
 
-    public void dismissWithAction(OnDismissAction r) {
+    public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) {
         if (mShowing) {
-            mBouncer.showWithDismissAction(r);
+            if (!afterKeyguardGone) {
+                mBouncer.showWithDismissAction(r);
+            } else {
+                mBouncer.show();
+                mAfterKeyguardGoneAction = r;
+            }
         }
         updateStates();
     }
@@ -245,6 +251,7 @@
                     mPhoneStatusBar.hideKeyguard();
                     mStatusBarWindowManager.setKeyguardFadingAway(false);
                     mViewMediatorCallback.keyguardGone();
+                    executeAfterKeyguardGoneAction();
                 }
             });
         } else {
@@ -266,11 +273,19 @@
             mStatusBarWindowManager.setKeyguardShowing(false);
             mBouncer.hide(true /* destroyView */);
             mViewMediatorCallback.keyguardGone();
+            executeAfterKeyguardGoneAction();
             updateStates();
         }
 
     }
 
+    private void executeAfterKeyguardGoneAction() {
+        if (mAfterKeyguardGoneAction != null) {
+            mAfterKeyguardGoneAction.onDismiss();
+            mAfterKeyguardGoneAction = null;
+        }
+    }
+
     /**
      * Dismisses the keyguard by going to the next screen or making it gone.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 6ae076f..b2009c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -301,6 +301,11 @@
     }
 
     @Override
+    public boolean isAntiFalsingNeeded() {
+        return false;
+    }
+
+    @Override
     public void onChildDismissed(View v) {
         Log.v(TAG, "User swiped heads up to dismiss");
         mBar.onHeadsUpDismissed();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 15a7047..9b59814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -64,6 +64,7 @@
     static final boolean CHATTY = false; // additional diagnostics, but not logspew
 
     private static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_signal_flightmode;
+    private static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
 
     // telephony
     boolean mHspaDataDistinguishable;
@@ -164,7 +165,7 @@
     public interface SignalCluster {
         void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
         void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
-                String contentDescription, String typeContentDescription);
+                String contentDescription, String typeContentDescription, boolean roaming);
         void setIsAirplaneMode(boolean is, int airplaneIcon);
     }
 
@@ -372,7 +373,8 @@
                     mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
                     mDataTypeIconId,
                     mContentDescriptionWimax,
-                    mContentDescriptionDataType);
+                    mContentDescriptionDataType,
+                    mDataTypeIconId == ROAMING_ICON);
         } else {
             // normal mobile data
             cluster.setMobileDataIndicators(
@@ -380,7 +382,8 @@
                     mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
                     mDataTypeIconId,
                     mContentDescriptionPhoneSignal,
-                    mContentDescriptionDataType);
+                    mContentDescriptionDataType,
+                    mDataTypeIconId == ROAMING_ICON);
         }
         cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
     }
@@ -777,11 +780,11 @@
 
         if (isCdma()) {
             if (isCdmaEri()) {
-                mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                mDataTypeIconId = ROAMING_ICON;
                 mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
             }
         } else if (mPhone.isNetworkRoaming()) {
-                mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                mDataTypeIconId = ROAMING_ICON;
                 mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
         }
     }
@@ -1195,11 +1198,11 @@
             mQSDataTypeIconId = 0;
             if (isCdma()) {
                 if (isCdmaEri()) {
-                    mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                    mDataTypeIconId = ROAMING_ICON;
                     mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
                 }
             } else if (mPhone.isNetworkRoaming()) {
-                mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                mDataTypeIconId = ROAMING_ICON;
                 mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
             }
         }
@@ -1544,8 +1547,7 @@
                             datatype.equals("g") ? R.drawable.stat_sys_data_fully_connected_g :
                             datatype.equals("h") ? R.drawable.stat_sys_data_fully_connected_h :
                             datatype.equals("lte") ? R.drawable.stat_sys_data_fully_connected_lte :
-                            datatype.equals("roam")
-                                    ? R.drawable.stat_sys_data_fully_connected_roam :
+                            datatype.equals("roam") ? ROAMING_ICON :
                             0;
                     mDemoQSDataTypeIconId =
                             datatype.equals("1x") ? R.drawable.ic_qs_signal_1x :
@@ -1572,7 +1574,8 @@
                             iconId,
                             mDemoDataTypeIconId,
                             "Demo",
-                            "Demo");
+                            "Demo",
+                            mDemoDataTypeIconId == ROAMING_ICON);
                 }
                 refreshViews();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 3a5a53b..6148feb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -18,18 +18,21 @@
 public interface SecurityController {
 
     boolean hasDeviceOwner();
+    boolean hasProfileOwner();
     String getDeviceOwnerName();
+    String getProfileOwnerName();
     boolean isVpnEnabled();
     String getVpnApp();
     boolean isLegacyVpn();
     String getLegacyVpnName();
     void disconnectFromVpn();
+    void onUserSwitched(int newUserId);
 
-    void addCallback(VpnCallback callback);
-    void removeCallback(VpnCallback callback);
+    void addCallback(SecurityControllerCallback callback);
+    void removeCallback(SecurityControllerCallback callback);
 
-    public interface VpnCallback {
-        void onVpnStateChanged();
+    public interface SecurityControllerCallback {
+        void onStateChanged();
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 499fe0b..a15ddaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.statusbar.policy;
 
+import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -52,11 +53,13 @@
     private final IConnectivityManager mConnectivityService = IConnectivityManager.Stub.asInterface(
                 ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
     private final DevicePolicyManager mDevicePolicyManager;
-    private final ArrayList<VpnCallback> mCallbacks = new ArrayList<VpnCallback>();
+    private final ArrayList<SecurityControllerCallback> mCallbacks
+            = new ArrayList<SecurityControllerCallback>();
 
     private VpnConfig mVpnConfig;
     private String mVpnName;
     private int mCurrentVpnNetworkId = NO_NETWORK;
+    private int mCurrentUserId;
 
     public SecurityControllerImpl(Context context) {
         mContext = context;
@@ -67,6 +70,7 @@
 
         // TODO: re-register network callback on user change.
         mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
+        mCurrentUserId = ActivityManager.getCurrentUser();
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -82,11 +86,22 @@
     }
 
     @Override
+    public boolean hasProfileOwner() {
+        return !TextUtils.isEmpty(mDevicePolicyManager.getProfileOwnerNameAsUser(mCurrentUserId));
+    }
+
+    @Override
     public String getDeviceOwnerName() {
         return mDevicePolicyManager.getDeviceOwnerName();
     }
 
     @Override
+    public String getProfileOwnerName() {
+        return mDevicePolicyManager.getProfileOwnerNameAsUser(mCurrentUserId);
+    }
+
+
+    @Override
     public boolean isVpnEnabled() {
         return mCurrentVpnNetworkId != NO_NETWORK;
     }
@@ -124,19 +139,25 @@
     }
 
     @Override
-    public void addCallback(VpnCallback callback) {
+    public void addCallback(SecurityControllerCallback callback) {
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         mCallbacks.remove(callback);
     }
 
     @Override
-    public void removeCallback(VpnCallback callback) {
+    public void removeCallback(SecurityControllerCallback callback) {
         if (callback == null || mCallbacks.contains(callback)) return;
         if (DEBUG) Log.d(TAG, "addCallback " + callback);
         mCallbacks.add(callback);
     }
 
+    @Override
+    public void onUserSwitched(int newUserId) {
+        mCurrentUserId = newUserId;
+        fireCallbacks();
+    }
+
     private void setCurrentNetid(int netId) {
         if (netId != mCurrentVpnNetworkId) {
             mCurrentVpnNetworkId = netId;
@@ -146,8 +167,8 @@
     }
 
     private void fireCallbacks() {
-        for (VpnCallback callback : mCallbacks) {
-            callback.onVpnStateChanged();
+        for (SecurityControllerCallback callback : mCallbacks) {
+            callback.onStateChanged();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 82efd1d..0aa1114 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -40,6 +40,7 @@
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.SpeedBumpView;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
 
@@ -195,6 +196,7 @@
             return true;
         }
     };
+    private PhoneStatusBar mPhoneStatusBar;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -640,6 +642,11 @@
         return (veto != null && veto.getVisibility() != View.GONE);
     }
 
+    @Override
+    public boolean isAntiFalsingNeeded() {
+        return mPhoneStatusBar.isFalsingThresholdNeeded();
+    }
+
     private void setSwipingInProgress(boolean isSwiped) {
         mSwipingInProgress = isSwiped;
         if(isSwiped) {
@@ -2185,6 +2192,10 @@
         mStackScrollAlgorithm.updateIsSmallScreen(mMaxLayoutHeight - qsMinHeight);
     }
 
+    public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
+        this.mPhoneStatusBar = phoneStatusBar;
+    }
+
     /**
      * A listener that is notified when some child locations might have changed.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index afd7216..cd3c1a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -747,6 +747,7 @@
             } else if (event.animationType ==
                     NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE) {
                 if (changingView.getVisibility() == View.GONE) {
+                    mHostLayout.getOverlay().remove(changingView);
                     continue;
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index f03c5eb..12c887e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -46,7 +45,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Vibrator;
-import android.provider.Settings.Global;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.KeyEvent;
@@ -58,6 +56,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
@@ -97,6 +96,7 @@
     private static final int TIMEOUT_DELAY_SHORT = 1500;
     private static final int TIMEOUT_DELAY_COLLAPSED = 4500;
     private static final int TIMEOUT_DELAY_SAFETY_WARNING = 5000;
+    private static final int TIMEOUT_DELAY_SAFETY_WARNING_TALKBACK = 25000;
     private static final int TIMEOUT_DELAY_EXPANDED = 10000;
 
     private static final int MSG_VOLUME_CHANGED = 0;
@@ -161,6 +161,7 @@
     private int mActiveStreamType = -1;
     /** All the slider controls mapped by stream type */
     private SparseArray<StreamControl> mStreamControls;
+    private final AccessibilityManager mAccessibilityManager;
 
     private enum StreamResources {
         BluetoothSCOStream(AudioManager.STREAM_BLUETOOTH_SCO,
@@ -332,6 +333,8 @@
         mContext = context;
         mZenController = zenController;
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
 
         // For now, only show master volume if master volume is supported
         final Resources res = context.getResources();
@@ -791,7 +794,8 @@
     }
 
     private void updateTimeoutDelay() {
-        mTimeoutDelay = sSafetyWarning != null ? TIMEOUT_DELAY_SAFETY_WARNING
+        mTimeoutDelay = sSafetyWarning != null ? mAccessibilityManager.isEnabled() ?
+                TIMEOUT_DELAY_SAFETY_WARNING_TALKBACK : TIMEOUT_DELAY_SAFETY_WARNING
                 : mActiveStreamType == AudioManager.STREAM_MUSIC ? TIMEOUT_DELAY_SHORT
                 : mZenPanelExpanded ? TIMEOUT_DELAY_EXPANDED
                 : isZenPanelVisible() ? TIMEOUT_DELAY_COLLAPSED
@@ -1214,6 +1218,7 @@
             }
             updateStates();
         }
+        updateTimeoutDelay();
         resetTimeout();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 0586a83d..acb4827 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -140,7 +140,8 @@
         @Override
         public void run() {
             getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
-                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
+                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */,
+                    false /* afterKeyguardGone */);
             mPanel.postDismiss(mDismissDelay);
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index c99e1fd..ac7fc25 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -31,10 +31,9 @@
 import android.provider.Settings.Global;
 import android.service.notification.Condition;
 import android.service.notification.ZenModeConfig;
-import android.text.format.DateFormat;
-import android.text.format.Time;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.MathUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.animation.AnimationUtils;
@@ -49,10 +48,7 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
-import java.text.SimpleDateFormat;
 import java.util.Arrays;
-import java.util.Date;
-import java.util.Locale;
 import java.util.Objects;
 
 public class ZenModePanel extends LinearLayout {
@@ -79,10 +75,10 @@
     private final Context mContext;
     private final LayoutInflater mInflater;
     private final H mHandler = new H();
-    private final Favorites mFavorites;
+    private final Prefs mPrefs;
     private final Interpolator mFastOutSlowInInterpolator;
-    private final int mHardWarningColor;
-    private final int mSoftWarningColor;
+    private final int mSubheadWarningColor;
+    private final int mSubheadColor;
 
     private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
 
@@ -92,7 +88,6 @@
     private TextView mZenSubheadExpanded;
     private View mMoreSettings;
     private LinearLayout mZenConditions;
-    private TextView mAlarmWarning;
 
     private Callback mCallback;
     private ZenModeController mController;
@@ -103,21 +98,21 @@
     private boolean mExpanded;
     private boolean mHidden = false;
     private int mSessionZen;
+    private int mAttachedZen;
     private Condition mSessionExitCondition;
-    private long mNextAlarm;
     private Condition[] mConditions;
     private Condition mTimeCondition;
 
     public ZenModePanel(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
-        mFavorites = new Favorites();
+        mPrefs = new Prefs();
         mInflater = LayoutInflater.from(mContext.getApplicationContext());
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
                 android.R.interpolator.fast_out_slow_in);
         final Resources res = mContext.getResources();
-        mHardWarningColor = res.getColor(R.color.system_warning_color);
-        mSoftWarningColor = res.getColor(R.color.qs_subhead);
+        mSubheadWarningColor = res.getColor(R.color.system_warning_color);
+        mSubheadColor = res.getColor(R.color.qs_subhead);
         if (DEBUG) Log.d(mTag, "new ZenModePanel");
     }
 
@@ -155,17 +150,16 @@
         });
 
         mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
-        mAlarmWarning = (TextView) findViewById(R.id.zen_alarm_warning);
     }
 
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         if (DEBUG) Log.d(mTag, "onAttachedToWindow");
-        mSessionZen = getSelectedZen(-1);
+        mAttachedZen = getSelectedZen(-1);
+        mSessionZen = mAttachedZen;
         mSessionExitCondition = copy(mExitCondition);
         refreshExitConditionText();
-        refreshNextAlarm();
         updateWidgets();
     }
 
@@ -173,6 +167,8 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
+        checkForAttachedZenChange();
+        mAttachedZen = -1;
         mSessionZen = -1;
         mSessionExitCondition = null;
         setExpanded(false);
@@ -184,6 +180,17 @@
         updateWidgets();
     }
 
+    private void checkForAttachedZenChange() {
+        final int selectedZen = getSelectedZen(-1);
+        if (DEBUG) Log.d(mTag, "selectedZen=" + selectedZen);
+        if (selectedZen != mAttachedZen) {
+            if (DEBUG) Log.d(mTag, "attachedZen: " + mAttachedZen + " -> " + selectedZen);
+            if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+                mPrefs.trackNoneSelected();
+            }
+        }
+    }
+
     private void setExpanded(boolean expanded) {
         if (expanded == mExpanded) return;
         mExpanded = expanded;
@@ -234,10 +241,6 @@
         updateWidgets();
     }
 
-    private Uri getExitConditionId() {
-        return getConditionId(mExitCondition);
-    }
-
     private static Uri getConditionId(Condition condition) {
         return condition != null ? condition.id : null;
     }
@@ -301,9 +304,7 @@
         final boolean zenOff = zen == Global.ZEN_MODE_OFF;
         final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
-        final boolean hasNextAlarm = mNextAlarm != 0;
         final boolean expanded = !mHidden && mExpanded;
-        final boolean showAlarmWarning = zenNone && expanded && hasNextAlarm;
 
         mZenButtons.setVisibility(mHidden ? GONE : VISIBLE);
         mZenSubhead.setVisibility(!mHidden && !zenOff ? VISIBLE : GONE);
@@ -311,26 +312,6 @@
         mZenSubheadCollapsed.setVisibility(!expanded ? VISIBLE : GONE);
         mMoreSettings.setVisibility(zenImportant && expanded ? VISIBLE : GONE);
         mZenConditions.setVisibility(!zenOff && expanded ? VISIBLE : GONE);
-        mAlarmWarning.setVisibility(zenNone && expanded && hasNextAlarm ? VISIBLE : GONE);
-        if (showAlarmWarning) {
-            final long exitTime = ZenModeConfig.tryParseCountdownConditionId(getExitConditionId());
-            final long now = System.currentTimeMillis();
-            final boolean alarmToday = time(mNextAlarm).yearDay == time(now).yearDay;
-            final String skeleton = (alarmToday ? "" : "E")
-                    + (DateFormat.is24HourFormat(mContext) ? "Hm" : "hma");
-            final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
-            final String alarm = new SimpleDateFormat(pattern).format(new Date(mNextAlarm));
-            final boolean isWarning = exitTime > 0 && mNextAlarm > now && mNextAlarm < exitTime;
-            if (isWarning) {
-                mAlarmWarning.setText(mContext.getString(R.string.zen_alarm_warning, alarm));
-                mAlarmWarning.setTextColor(mHardWarningColor);
-            } else {
-                mAlarmWarning.setText(mContext.getString(alarmToday
-                        ? R.string.zen_alarm_information_time
-                        : R.string.zen_alarm_information_day_time, alarm));
-                mAlarmWarning.setTextColor(mSoftWarningColor);
-            }
-        }
 
         if (zenNone) {
             mZenSubheadExpanded.setText(R.string.zen_no_interruptions_with_warning);
@@ -339,12 +320,8 @@
             mZenSubheadExpanded.setText(R.string.zen_important_interruptions);
             mZenSubheadCollapsed.setText(mExitConditionText);
         }
-    }
-
-    private static Time time(long millis) {
-        final Time t = new Time();
-        t.set(millis);
-        return t;
+        mZenSubheadExpanded.setTextColor(zenNone && mPrefs.isNoneDangerous()
+                ? mSubheadWarningColor : mSubheadColor);
     }
 
     private Condition parseExistingTimeCondition(Condition condition) {
@@ -373,15 +350,6 @@
                 Condition.FLAG_RELEVANT_NOW);
     }
 
-    private void refreshNextAlarm() {
-        mNextAlarm = mController.getNextAlarm();
-    }
-
-    private void handleNextAlarmChanged() {
-        refreshNextAlarm();
-        updateWidgets();
-    }
-
     private void handleUpdateConditions(Condition[] conditions) {
         mConditions = conditions;
         handleUpdateConditions();
@@ -429,7 +397,7 @@
             }
         }
         if (DEBUG) Log.d(mTag, "Selecting a default");
-        final int favoriteIndex = mFavorites.getMinuteIndex();
+        final int favoriteIndex = mPrefs.getMinuteIndex();
         if (favoriteIndex == -1) {
             getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
         } else {
@@ -579,9 +547,9 @@
         }
         setExitCondition(condition);
         if (condition == null) {
-            mFavorites.setMinuteIndex(-1);
+            mPrefs.setMinuteIndex(-1);
         } else if (ZenModeConfig.isValidCountdownConditionId(condition.id) && mBucketIndex != -1) {
-            mFavorites.setMinuteIndex(mBucketIndex);
+            mPrefs.setMinuteIndex(mBucketIndex);
         }
         mSessionExitCondition = copy(condition);
     }
@@ -618,18 +586,12 @@
         public void onExitConditionChanged(Condition exitCondition) {
             mHandler.obtainMessage(H.EXIT_CONDITION_CHANGED, exitCondition).sendToTarget();
         }
-
-        @Override
-        public void onNextAlarmChanged() {
-            mHandler.sendEmptyMessage(H.NEXT_ALARM_CHANGED);
-        }
     };
 
     private final class H extends Handler {
         private static final int UPDATE_CONDITIONS = 1;
         private static final int EXIT_CONDITION_CHANGED = 2;
         private static final int UPDATE_ZEN = 3;
-        private static final int NEXT_ALARM_CHANGED = 4;
 
         private H() {
             super(Looper.getMainLooper());
@@ -643,8 +605,6 @@
                 handleExitConditionChanged((Condition) msg.obj);
             } else if (msg.what == UPDATE_ZEN) {
                 handleUpdateZen(msg.arg1);
-            } else if (msg.what == NEXT_ALARM_CHANGED) {
-                handleNextAlarmChanged();
             }
         }
     }
@@ -661,14 +621,32 @@
         Condition condition;
     }
 
-    private final class Favorites implements OnSharedPreferenceChangeListener {
+    private final class Prefs implements OnSharedPreferenceChangeListener {
         private static final String KEY_MINUTE_INDEX = "minuteIndex";
+        private static final String KEY_NONE_SELECTED = "noneSelected";
+
+        private final int mNoneDangerousThreshold;
 
         private int mMinuteIndex;
+        private int mNoneSelected;
 
-        private Favorites() {
+        private Prefs() {
+            mNoneDangerousThreshold = mContext.getResources()
+                    .getInteger(R.integer.zen_mode_alarm_warning_threshold);
             prefs().registerOnSharedPreferenceChangeListener(this);
             updateMinuteIndex();
+            updateNoneSelected();
+        }
+
+        public boolean isNoneDangerous() {
+            return mNoneSelected < mNoneDangerousThreshold;
+        }
+
+        public void trackNoneSelected() {
+            mNoneSelected = clampNoneSelected(mNoneSelected + 1);
+            if (DEBUG) Log.d(mTag, "Setting none selected: " + mNoneSelected + " threshold="
+                    + mNoneDangerousThreshold);
+            prefs().edit().putInt(KEY_NONE_SELECTED, mNoneSelected).apply();
         }
 
         public int getMinuteIndex() {
@@ -676,9 +654,9 @@
         }
 
         public void setMinuteIndex(int minuteIndex) {
-            minuteIndex = clamp(minuteIndex);
+            minuteIndex = clampIndex(minuteIndex);
             if (minuteIndex == mMinuteIndex) return;
-            mMinuteIndex = clamp(minuteIndex);
+            mMinuteIndex = clampIndex(minuteIndex);
             if (DEBUG) Log.d(mTag, "Setting favorite minute index: " + mMinuteIndex);
             prefs().edit().putInt(KEY_MINUTE_INDEX, mMinuteIndex).apply();
         }
@@ -686,6 +664,7 @@
         @Override
         public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
             updateMinuteIndex();
+            updateNoneSelected();
         }
 
         private SharedPreferences prefs() {
@@ -693,12 +672,21 @@
         }
 
         private void updateMinuteIndex() {
-            mMinuteIndex = clamp(prefs().getInt(KEY_MINUTE_INDEX, DEFAULT_BUCKET_INDEX));
+            mMinuteIndex = clampIndex(prefs().getInt(KEY_MINUTE_INDEX, DEFAULT_BUCKET_INDEX));
             if (DEBUG) Log.d(mTag, "Favorite minute index: " + mMinuteIndex);
         }
 
-        private int clamp(int index) {
-            return Math.max(-1, Math.min(MINUTE_BUCKETS.length - 1, index));
+        private int clampIndex(int index) {
+            return MathUtils.constrain(index, -1, MINUTE_BUCKETS.length - 1);
+        }
+
+        private void updateNoneSelected() {
+            mNoneSelected = clampNoneSelected(prefs().getInt(KEY_NONE_SELECTED, 0));
+            if (DEBUG) Log.d(mTag, "None selected: " + mNoneSelected);
+        }
+
+        private int clampNoneSelected(int noneSelected) {
+            return MathUtils.constrain(noneSelected, 0, Integer.MAX_VALUE);
         }
     }
 
diff --git a/packages/VpnDialogs/res/values-fi/strings.xml b/packages/VpnDialogs/res/values-fi/strings.xml
index 4a0c529..23fae48 100644
--- a/packages/VpnDialogs/res/values-fi/strings.xml
+++ b/packages/VpnDialogs/res/values-fi/strings.xml
@@ -16,10 +16,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for prompt (3183836924226407828) -->
-    <skip />
-    <!-- no translation found for warning (809658604548412033) -->
-    <skip />
+    <string name="prompt" msgid="3183836924226407828">"Yhteyspyyntö"</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> haluaa tehdä asetukset VPN-yhteydellä, jonka kautta sovellus voi valvoa verkkoliikennettä. Hyväksy vain, jos lähde on luotettava. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; näkyy ruudun yläreunassa, kun VPN on käytössä."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN on yhdistetty"</string>
     <string name="configure" msgid="4905518375574791375">"Asetukset"</string>
     <string name="disconnect" msgid="971412338304200056">"Katkaise yhteys"</string>
diff --git a/packages/VpnDialogs/res/values-ka-rGE/strings.xml b/packages/VpnDialogs/res/values-ka-rGE/strings.xml
index beaeb66..61f3b0f 100644
--- a/packages/VpnDialogs/res/values-ka-rGE/strings.xml
+++ b/packages/VpnDialogs/res/values-ka-rGE/strings.xml
@@ -16,10 +16,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for prompt (3183836924226407828) -->
-    <skip />
-    <!-- no translation found for warning (809658604548412033) -->
-    <skip />
+    <string name="prompt" msgid="3183836924226407828">"კავშირის მოთხოვნა"</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> სურს დააყენოს VPN კავშირი, რაც ქსელის ტრაფიკის მონიტორინგის საშუალებას იძლევა. მიიღოთ მხოლოდ ისეთ შემთხვევაში, თუ წყაროს ენდობით. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; თქვენი ეკრანის სიის თავში გამოჩნდება, როდესაც VPN აქტიურია."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN დაკავშირებულია"</string>
     <string name="configure" msgid="4905518375574791375">"კონფიგურაცია"</string>
     <string name="disconnect" msgid="971412338304200056">"კავშირის გაწყვეტა"</string>
diff --git a/packages/VpnDialogs/res/values-ms-rMY/strings.xml b/packages/VpnDialogs/res/values-ms-rMY/strings.xml
index 41f85923..8ea682f 100644
--- a/packages/VpnDialogs/res/values-ms-rMY/strings.xml
+++ b/packages/VpnDialogs/res/values-ms-rMY/strings.xml
@@ -16,10 +16,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for prompt (3183836924226407828) -->
-    <skip />
-    <!-- no translation found for warning (809658604548412033) -->
-    <skip />
+    <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyediakan sambungan VPN yang membenarkan apl memantau trafik rangkaian. Terima hanya jika anda mempercayai sumber. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; terpapar pada bahagian atas skrin anda apabila VPN aktif."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN telah disambungkan"</string>
     <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string>
     <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string>
diff --git a/packages/VpnDialogs/res/values-si-rLK/strings.xml b/packages/VpnDialogs/res/values-si-rLK/strings.xml
index 511a641..5f54821 100644
--- a/packages/VpnDialogs/res/values-si-rLK/strings.xml
+++ b/packages/VpnDialogs/res/values-si-rLK/strings.xml
@@ -16,10 +16,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for prompt (3183836924226407828) -->
-    <skip />
-    <!-- no translation found for warning (809658604548412033) -->
-    <skip />
+    <string name="prompt" msgid="3183836924226407828">"සම්බන්ධතා ඉල්ලීම"</string>
+    <string name="warning" msgid="809658604548412033">"ජාල තදබදය නිරීක්ෂණය කිරීමට ඉඩ දෙන VPN සම්බන්ධතාවක් සැකසීමට <xliff:g id="APP">%s</xliff:g> අවශ්‍යය වේ. ප්‍රභවය ඔබ විශ්වාස කරන්නේ නම් පමණක් පිළිගන්න. VPN සක්‍රිය විට &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt;."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN සම්බන්ධිතයි"</string>
     <string name="configure" msgid="4905518375574791375">"වින්‍යාස කිරීම"</string>
     <string name="disconnect" msgid="971412338304200056">"විසන්ධි කරන්න"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
index 11aa2a6..a77ba3b 100644
--- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
@@ -16,10 +16,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for prompt (3183836924226407828) -->
-    <skip />
-    <!-- no translation found for warning (809658604548412033) -->
-    <skip />
+    <string name="prompt" msgid="3183836924226407828">"连接请求"</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>想要设置一个VPN连接(可被用于监控网络流量)。请只在您信任该来源的情况下才接受此请求。在VPN处于活动状态时,您的屏幕顶部会显示 &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; 图标。"</string>
     <string name="legacy_title" msgid="192936250066580964">"已连接VPN"</string>
     <string name="configure" msgid="4905518375574791375">"配置"</string>
     <string name="disconnect" msgid="971412338304200056">"断开连接"</string>
diff --git a/packages/VpnDialogs/res/values-zh-rHK/strings.xml b/packages/VpnDialogs/res/values-zh-rHK/strings.xml
index e2a1897..fa77c6c 100644
--- a/packages/VpnDialogs/res/values-zh-rHK/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rHK/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"連線要求"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿任意接受要求。&lt;br /&gt; &lt;br /&gt;VPN 啟用時,畫面頂端會顯示 &lt;img src=vpn_icon /&gt;。"</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿隨意接受要求。&lt;br /&gt; &lt;br /&gt;VPN 啟用時,畫面頂端會顯示 &lt;img src=vpn_icon /&gt;。"</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string>
     <string name="configure" msgid="4905518375574791375">"設定"</string>
     <string name="disconnect" msgid="971412338304200056">"中斷連線"</string>
diff --git a/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java b/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java
index 71b0d53..6f79f58 100644
--- a/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java
+++ b/policy/src/com/android/internal/policy/impl/EnableAccessibilityController.java
@@ -83,6 +83,7 @@
 
 
     private final Context mContext;
+    private final Runnable mOnAccessibilityEnabledCallback;
     private final UserManager mUserManager;
     private final TextToSpeech mTts;
     private final Ringtone mTone;
@@ -97,8 +98,9 @@
     private float mSecondPointerDownX;
     private float mSecondPointerDownY;
 
-    public EnableAccessibilityController(Context context) {
+    public EnableAccessibilityController(Context context, Runnable onAccessibilityEnabledCallback) {
         mContext = context;
+        mOnAccessibilityEnabledCallback = onAccessibilityEnabledCallback;
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mTts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
             @Override
@@ -275,5 +277,7 @@
                 /* ignore */
             }
         }
+
+        mOnAccessibilityEnabledCallback.run();
     }
 }
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index ae94654..41695c1 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -1073,7 +1073,13 @@
             // is dismissed on the first down while the global gesture is a long press
             // with two fingers anywhere on the screen.
             if (EnableAccessibilityController.canEnableAccessibilityViaGesture(mContext)) {
-                mEnableAccessibilityController = new EnableAccessibilityController(mContext);
+                mEnableAccessibilityController = new EnableAccessibilityController(mContext,
+                        new Runnable() {
+                    @Override
+                    public void run() {
+                        dismiss();
+                    }
+                });
                 super.setCanceledOnTouchOutside(false);
             } else {
                 mEnableAccessibilityController = null;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e240127..a13da609 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3206,8 +3206,10 @@
                 Context.WINDOW_SERVICE);
         if (windowService != null) {
             final Display display = windowService.getDefaultDisplay();
-            if (display.getDisplayId() == Display.DEFAULT_DISPLAY &&
-                    a.hasValue(R.styleable.Window_windowOutsetBottom)) {
+            final boolean shouldUseBottomOutset =
+                    display.getDisplayId() == Display.DEFAULT_DISPLAY
+                            || (getForcedWindowFlags() & FLAG_FULLSCREEN) != 0;
+            if (shouldUseBottomOutset && a.hasValue(R.styleable.Window_windowOutsetBottom)) {
                 if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
                 a.getValue(R.styleable.Window_windowOutsetBottom,
                         mOutsetBottom);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 5a836c8..e382a9f 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -545,6 +545,7 @@
     private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
     private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
     private static final int MSG_HIDE_BOOT_MESSAGE = 11;
+    private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -590,6 +591,9 @@
                 case MSG_HIDE_BOOT_MESSAGE:
                     handleHideBootMessage();
                     break;
+                case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
+                    launchVoiceAssistWithWakeLock(msg.arg1 != 0);
+                    break;
             }
         }
     }
@@ -2342,11 +2346,11 @@
         } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
             if (!down) {
                 Intent voiceIntent;
-                if (!keyguardOn && mPowerManager.isInteractive()) {
+                if (!keyguardOn) {
                     voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
                 } else {
                     voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
-                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardOn);
+                    voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
                 }
                 mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
             }
@@ -4445,6 +4449,19 @@
                 }
                 break;
             }
+            case KeyEvent.KEYCODE_VOICE_ASSIST: {
+                // Only do this if we would otherwise not pass it to the user. In that case,
+                // interceptKeyBeforeDispatching would apply a similar but different policy in
+                // order to invoke voice assist actions. Note that we need to make a copy of the
+                // key event here because the original key event will be recycled when we return.
+                if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
+                    mBroadcastWakeLock.acquire();
+                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
+                            keyguardActive ? 1 : 0, 0);
+                    msg.setAsynchronous(true);
+                    msg.sendToTarget();
+                }
+            }
         }
 
         if (useHapticFeedback) {
@@ -4551,6 +4568,14 @@
         }
     }
 
+    void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
+        Intent voiceIntent =
+            new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+        voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
+        mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
+        mBroadcastWakeLock.release();
+    }
+
     BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index ac0ca0a..af5c13d 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -708,6 +708,7 @@
                      // Send an event to the end of the drag gesture.
                      sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
                  }
+                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
             case MotionEvent.ACTION_UP: {
                 mAms.onTouchInteractionEnd();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 9674ca2..3e7a7e4 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1963,8 +1963,9 @@
         return packages;
     }
 
-    // Called from the backup task: record that the given app has been successfully
-    // backed up at least once
+    // Called from the backup tasks: record that the given app has been successfully
+    // backed up at least once.  This includes both key/value and full-data backups
+    // through the transport.
     void logBackupComplete(String packageName) {
         if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) return;
 
@@ -3837,6 +3838,7 @@
                         // Success!
                         EventLog.writeEvent(EventLogTags.FULL_BACKUP_SUCCESS,
                                 currentPackage.packageName);
+                        logBackupComplete(currentPackage.packageName);
                     }
                     cleanUpPipes(transportPipes);
                     cleanUpPipes(enginePipes);
@@ -8632,10 +8634,9 @@
             skip = true;
         }
 
-        if (!mAutoRestore || !mProvisioned) {
+        if (!mAutoRestore) {
             if (DEBUG) {
-                Slog.w(TAG, "Non-restorable state: auto=" + mAutoRestore
-                        + " prov=" + mProvisioned);
+                Slog.w(TAG, "Non-restorable state: auto=" + mAutoRestore);
             }
             skip = true;
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8bb094b..0919f77 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -185,7 +185,7 @@
     private static final String TAG = "ConnectivityService";
 
     private static final boolean DBG = true;
-    private static final boolean VDBG = true; // STOPSHIP
+    private static final boolean VDBG = false;
 
     // network sampling debugging
     private static final boolean SAMPLE_DBG = false;
@@ -830,11 +830,11 @@
             // network is blocked; clone and override state
             info = new NetworkInfo(info);
             info.setDetailedState(DetailedState.BLOCKED, null, null);
-            if (VDBG) log("returning Blocked NetworkInfo");
+            if (DBG) log("returning Blocked NetworkInfo");
         }
         if (mLockdownTracker != null) {
             info = mLockdownTracker.augmentNetworkInfo(info);
-            if (VDBG) log("returning Locked NetworkInfo");
+            if (DBG) log("returning Locked NetworkInfo");
         }
         return info;
     }
@@ -1202,7 +1202,7 @@
                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
             }
         }
-        if (VDBG) log("Adding " + bestRoute + " for interface " + bestRoute.getInterface());
+        if (DBG) log("Adding " + bestRoute + " for interface " + bestRoute.getInterface());
         try {
             mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
         } catch (Exception e) {
@@ -1401,7 +1401,7 @@
                 mInitialBroadcast = new Intent(intent);
             }
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            if (VDBG) {
+            if (DBG) {
                 log("sendStickyBroadcast: action=" + intent.getAction());
             }
 
@@ -1558,7 +1558,7 @@
         }
 
         try {
-            if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
+            if (DBG) log("Setting MTU size: " + iface + ", " + mtu);
             mNetd.setMtu(iface, mtu);
         } catch (Exception e) {
             Slog.e(TAG, "exception in setMtu()" + e);
@@ -1579,7 +1579,7 @@
         }
 
         if (values == null || values.length != 6) {
-            if (VDBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
+            if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults");
             tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES;
             values = tcpBufferSizes.split(",");
         }
@@ -1587,7 +1587,7 @@
         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
 
         try {
-            if (VDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
+            if (DBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
 
             final String prefix = "/sys/kernel/ipv4/tcp_";
             FileUtils.stringToFile(prefix + "rmem_min", values[0]);
@@ -1750,7 +1750,7 @@
         }
         if (officialNai != null && officialNai.equals(nai)) return true;
         if (officialNai != null || VDBG) {
-            loge(msg + " - validateNetworkAgent found mismatched netId: " + officialNai +
+            loge(msg + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
                 " - " + nai);
         }
         return false;
@@ -1794,7 +1794,7 @@
                         loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
                     } else {
                         if (VDBG) {
-                            log("Update of Linkproperties for " + nai.name() +
+                            log("Update of LinkProperties for " + nai.name() +
                                     "; created=" + nai.created);
                         }
                         LinkProperties oldLp = nai.linkProperties;
@@ -2073,11 +2073,10 @@
             for (int i = 0; i < nai.networkRequests.size(); i++) {
                 NetworkRequest request = nai.networkRequests.valueAt(i);
                 NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
-                if (VDBG) {
-                    log(" checking request " + request + ", currentNetwork = " +
-                            (currentNetwork != null ? currentNetwork.name() : "null"));
-                }
                 if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
+                    if (DBG) {
+                        log("Checking for replacement network to handle request " + request );
+                    }
                     mNetworkForRequestId.remove(request.requestId);
                     sendUpdatedScoreToFactories(request, 0);
                     NetworkAgentInfo alternative = null;
@@ -2091,8 +2090,11 @@
                             alternative = existing;
                         }
                     }
-                    if (alternative != null && !toActivate.contains(alternative)) {
-                        toActivate.add(alternative);
+                    if (alternative != null) {
+                        if (DBG) log(" found replacement in " + alternative.name());
+                        if (!toActivate.contains(alternative)) {
+                            toActivate.add(alternative);
+                        }
                     }
                 }
             }
@@ -2115,9 +2117,9 @@
         // Check for the best currently alive network that satisfies this request
         NetworkAgentInfo bestNetwork = null;
         for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
-            if (VDBG) log("handleRegisterNetworkRequest checking " + network.name());
+            if (DBG) log("handleRegisterNetworkRequest checking " + network.name());
             if (newCap.satisfiedByNetworkCapabilities(network.networkCapabilities)) {
-                if (VDBG) log("apparently satisfied.  currentScore=" + network.currentScore);
+                if (DBG) log("apparently satisfied.  currentScore=" + network.currentScore);
                 if ((bestNetwork == null) || bestNetwork.currentScore < network.currentScore) {
                     if (!nri.isRequest) {
                         // Not setting bestNetwork here as a listening NetworkRequest may be
@@ -2132,7 +2134,7 @@
             }
         }
         if (bestNetwork != null) {
-            if (VDBG) log("using " + bestNetwork.name());
+            if (DBG) log("using " + bestNetwork.name());
             if (bestNetwork.networkInfo.isConnected()) {
                 // Cancel any lingering so the linger timeout doesn't teardown this network
                 // even though we have a request for it.
@@ -2173,7 +2175,7 @@
                 for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
                     if (nai.networkRequests.get(nri.request.requestId) != null) {
                         nai.networkRequests.remove(nri.request.requestId);
-                        if (VDBG) {
+                        if (DBG) {
                             log(" Removing from current network " + nai.name() +
                                     ", leaving " + nai.networkRequests.size() +
                                     " requests.");
@@ -3557,7 +3559,7 @@
             // Check for  apps that can handle provisioning first
             Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP);
             List<String> carrierPackages =
-                    mTelephonyManager.getCarrierPackageNamesForBroadcastIntent(provisioningIntent);
+                    mTelephonyManager.getCarrierPackageNamesForIntent(provisioningIntent);
             if (carrierPackages != null && !carrierPackages.isEmpty()) {
                 if (carrierPackages.size() != 1) {
                     if (DBG) log("Multiple matching carrier apps found, launching the first.");
@@ -3920,7 +3922,7 @@
 
     private void handleNetworkSamplingTimeout() {
 
-        log("Sampling interval elapsed, updating statistics ..");
+        if (SAMPLE_DBG) log("Sampling interval elapsed, updating statistics ..");
 
         // initialize list of interfaces ..
         Map<String, SamplingDataTracker.SamplingSnapshot> mapIfaceToSample =
@@ -3951,13 +3953,15 @@
             }
         }
 
-        log("Done.");
+        if (SAMPLE_DBG) log("Done.");
 
         int samplingIntervalInSeconds = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
                 DEFAULT_SAMPLING_INTERVAL_IN_SECONDS);
 
-        if (DBG) log("Setting timer for " + String.valueOf(samplingIntervalInSeconds) + "seconds");
+        if (SAMPLE_DBG) {
+            log("Setting timer for " + String.valueOf(samplingIntervalInSeconds) + "seconds");
+        }
 
         setAlarm(samplingIntervalInSeconds * 1000, mSampleIntervalElapsedIntent);
     }
@@ -4125,7 +4129,7 @@
     }
 
     private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
-        if (VDBG) log("Got NetworkFactory Messenger for " + nfi.name);
+        if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
         mNetworkFactoryInfos.put(nfi.messenger, nfi);
         nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
     }
@@ -4139,10 +4143,10 @@
     private void handleUnregisterNetworkFactory(Messenger messenger) {
         NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
         if (nfi == null) {
-            if (VDBG) log("Failed to find Messenger in unregisterNetworkFactory");
+            loge("Failed to find Messenger in unregisterNetworkFactory");
             return;
         }
-        if (VDBG) log("unregisterNetworkFactory for " + nfi.name);
+        if (DBG) log("unregisterNetworkFactory for " + nfi.name);
     }
 
     /**
@@ -4180,7 +4184,7 @@
         synchronized (this) {
             nai.networkMonitor.systemReady = mSystemReady;
         }
-        if (VDBG) log("registerNetworkAgent " + nai);
+        if (DBG) log("registerNetworkAgent " + nai);
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
     }
 
@@ -4241,6 +4245,7 @@
         }
         for (String iface : interfaceDiff.added) {
             try {
+                if (DBG) log("Adding iface " + iface + " to network " + netId);
                 mNetd.addInterfaceToNetwork(iface, netId);
             } catch (Exception e) {
                 loge("Exception adding interface: " + e);
@@ -4248,6 +4253,7 @@
         }
         for (String iface : interfaceDiff.removed) {
             try {
+                if (DBG) log("Removing iface " + iface + " from network " + netId);
                 mNetd.removeInterfaceFromNetwork(iface, netId);
             } catch (Exception e) {
                 loge("Exception removing interface: " + e);
@@ -4272,22 +4278,29 @@
         // do this twice, adding non-nexthop routes first, then routes they are dependent on
         for (RouteInfo route : routeDiff.added) {
             if (route.hasGateway()) continue;
+            if (DBG) log("Adding Route [" + route + "] to network " + netId);
             try {
                 mNetd.addRoute(netId, route);
             } catch (Exception e) {
-                loge("Exception in addRoute for non-gateway: " + e);
+                if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
+                    loge("Exception in addRoute for non-gateway: " + e);
+                }
             }
         }
         for (RouteInfo route : routeDiff.added) {
             if (route.hasGateway() == false) continue;
+            if (DBG) log("Adding Route [" + route + "] to network " + netId);
             try {
                 mNetd.addRoute(netId, route);
             } catch (Exception e) {
-                loge("Exception in addRoute for gateway: " + e);
+                if ((route.getGateway() instanceof Inet4Address) || VDBG) {
+                    loge("Exception in addRoute for gateway: " + e);
+                }
             }
         }
 
         for (RouteInfo route : routeDiff.removed) {
+            if (DBG) log("Removing Route [" + route + "] from network " + netId);
             try {
                 mNetd.removeRoute(netId, route);
             } catch (Exception e) {
@@ -4306,6 +4319,7 @@
                     loge("no dns provided for netId " + netId + ", so using defaults");
                 }
             }
+            if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
             try {
                 mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses),
                     newLp.getDomains());
@@ -4395,7 +4409,10 @@
         msg.obj = o;
         msg.what = notificationType;
         try {
-            if (VDBG) log("sending notification " + notificationType + " for " + nri.request);
+            if (VDBG) {
+                log("sending notification " + notifyTypeToName(notificationType) +
+                        " for " + nri.request);
+            }
             nri.messenger.send(msg);
         } catch (RemoteException e) {
             // may occur naturally in the race of binder death.
@@ -4418,7 +4435,7 @@
     }
 
     private void makeDefault(NetworkAgentInfo newNetwork) {
-        if (VDBG) log("Switching to new default network: " + newNetwork);
+        if (DBG) log("Switching to new default network: " + newNetwork);
         mActiveDefaultNetwork = newNetwork.networkInfo.getType();
         setupDataActivityTracking(newNetwork);
         try {
@@ -4444,7 +4461,7 @@
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
             NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
             if (newNetwork == currentNetwork) {
-                if (VDBG) log("Network " + newNetwork.name() + " was already satisfying" +
+                if (DBG) log("Network " + newNetwork.name() + " was already satisfying" +
                               " request " + nri.request.requestId + ". No change.");
                 keep = true;
                 continue;
@@ -4468,12 +4485,12 @@
                 if (currentNetwork == null ||
                         currentNetwork.currentScore < newNetwork.currentScore) {
                     if (currentNetwork != null) {
-                        if (VDBG) log("   accepting network in place of " + currentNetwork.name());
+                        if (DBG) log("   accepting network in place of " + currentNetwork.name());
                         currentNetwork.networkRequests.remove(nri.request.requestId);
                         currentNetwork.networkLingered.add(nri.request);
                         affectedNetworks.add(currentNetwork);
                     } else {
-                        if (VDBG) log("   accepting network in place of null");
+                        if (DBG) log("   accepting network in place of null");
                     }
                     mNetworkForRequestId.put(nri.request.requestId, newNetwork);
                     newNetwork.addRequest(nri.request);
@@ -4574,7 +4591,7 @@
                     loge("  " + newNetwork.networkRequests.valueAt(i));
                 }
             }
-            if (VDBG) log("Validated network turns out to be unwanted.  Tear it down.");
+            if (DBG) log("Validated network turns out to be unwanted.  Tear it down.");
             newNetwork.asyncChannel.disconnect();
         }
     }
@@ -4745,7 +4762,7 @@
     }
 
     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
-        if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name());
+        if (DBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
         for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
             NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
             NetworkRequestInfo nri = mNetworkRequests.get(nr);
@@ -4754,6 +4771,20 @@
         }
     }
 
+    private String notifyTypeToName(int notifyType) {
+        switch (notifyType) {
+            case ConnectivityManager.CALLBACK_PRECHECK:    return "PRECHECK";
+            case ConnectivityManager.CALLBACK_AVAILABLE:   return "AVAILABLE";
+            case ConnectivityManager.CALLBACK_LOSING:      return "LOSING";
+            case ConnectivityManager.CALLBACK_LOST:        return "LOST";
+            case ConnectivityManager.CALLBACK_UNAVAIL:     return "UNAVAILABLE";
+            case ConnectivityManager.CALLBACK_CAP_CHANGED: return "CAP_CHANGED";
+            case ConnectivityManager.CALLBACK_IP_CHANGED:  return "IP_CHANGED";
+            case ConnectivityManager.CALLBACK_RELEASED:    return "RELEASED";
+        }
+        return "UNKNOWN";
+    }
+
     private LinkProperties getLinkPropertiesForTypeInternal(int networkType) {
         NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
         if (nai != null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 972a86d..6310764 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1198,11 +1198,12 @@
      */
     private boolean mUserIsMonkey;
 
-    /** Flag whether the device has a recents UI */
-    final boolean mHasRecents;
+    /** Flag whether the device has a Recents UI */
+    boolean mHasRecents;
 
-    final int mThumbnailWidth;
-    final int mThumbnailHeight;
+    /** The dimensions of the thumbnails in the Recents UI. */
+    int mThumbnailWidth;
+    int mThumbnailHeight;
 
     final ServiceThread mHandlerThread;
     final MainHandler mHandler;
@@ -2257,11 +2258,6 @@
         mConfigurationSeq = mConfiguration.seq = 1;
         mProcessCpuTracker.init();
 
-        final Resources res = mContext.getResources();
-        mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
-        mThumbnailWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
-        mThumbnailHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
-
         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
         mStackSupervisor = new ActivityStackSupervisor(this);
@@ -3816,6 +3812,11 @@
      * of affiliations.
      */
     void cleanupRecentTasksLocked(int userId) {
+        if (mRecentTasks == null) {
+            // Happens when called from the packagemanager broadcast before boot.
+            return;
+        }
+
         final HashMap<ComponentName, ActivityInfo> availActCache = new HashMap<>();
         final HashMap<String, ApplicationInfo> availAppCache = new HashMap<>();
         final IPackageManager pm = AppGlobals.getPackageManager();
@@ -8947,6 +8948,14 @@
         return false;
     }
 
+    private void checkTime(long startTime, String where) {
+        long now = SystemClock.elapsedRealtime();
+        if ((now-startTime) > 1000) {
+            // If we are taking more than a second, log about it.
+            Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+        }
+    }
+
     private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
             String name, IBinder token, boolean stable, int userId) {
         ContentProviderRecord cpr;
@@ -8954,6 +8963,8 @@
         ProviderInfo cpi = null;
 
         synchronized(this) {
+            long startTime = SystemClock.elapsedRealtime();
+
             ProcessRecord r = null;
             if (caller != null) {
                 r = getRecordForAppLocked(caller);
@@ -8967,6 +8978,8 @@
 
             boolean checkCrossUser = true;
 
+            checkTime(startTime, "getContentProviderImpl: getProviderByName");
+
             // First check if this content provider has been published...
             cpr = mProviderMap.getProviderByName(name, userId);
             // If that didn't work, check if it exists for user 0 and then
@@ -8991,10 +9004,12 @@
             if (providerRunning) {
                 cpi = cpr.info;
                 String msg;
+                checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
                 if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
                         != null) {
                     throw new SecurityException(msg);
                 }
+                checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
 
                 if (r != null && cpr.canRunHere(r)) {
                     // This provider has been published or is in the process
@@ -9010,6 +9025,8 @@
 
                 final long origId = Binder.clearCallingIdentity();
 
+                checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
+
                 // In this case the provider instance already exists, so we can
                 // return it right away.
                 conn = incProviderCountLocked(r, cpr, token, stable);
@@ -9019,7 +9036,9 @@
                         // make sure to count it as being accessed and thus
                         // back up on the LRU list.  This is good because
                         // content providers are often expensive to start.
+                        checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
                         updateLruProcessLocked(cpr.proc, false, null);
+                        checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
                     }
                 }
 
@@ -9032,7 +9051,9 @@
                             Process.killProcess(cpr.proc.pid);
                         }
                     }
+                    checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
                     boolean success = updateOomAdjLocked(cpr.proc);
+                    checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
                     if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
                     // NOTE: there is still a race here where a signal could be
                     // pending on the process even though we managed to update its
@@ -9047,7 +9068,9 @@
                                 "Existing provider " + cpr.name.flattenToShortString()
                                 + " is crashing; detaching " + r);
                         boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
+                        checkTime(startTime, "getContentProviderImpl: before appDied");
                         appDiedLocked(cpr.proc);
+                        checkTime(startTime, "getContentProviderImpl: after appDied");
                         if (!lastRef) {
                             // This wasn't the last ref our process had on
                             // the provider...  we have now been killed, bail.
@@ -10675,6 +10698,14 @@
         }
     }
 
+    /** Loads resources after the current configuration has been set. */
+    private void loadResourcesOnSystemReady() {
+        final Resources res = mContext.getResources();
+        mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
+        mThumbnailWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
+        mThumbnailHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
+    }
+
     public boolean testIsSystemReady() {
         // no need to synchronize(this) just to read & return the value
         return mSystemReady;
@@ -10956,6 +10987,7 @@
         }
 
         retrieveSettings();
+        loadResourcesOnSystemReady();
 
         synchronized (this) {
             readGrantedUriPermissionsLocked();
@@ -15203,6 +15235,10 @@
             final int is24Hour = intent.getBooleanExtra(
                     Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
             mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+            BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+            synchronized (stats) {
+                stats.noteCurrentTimeChangedLocked();
+            }
         }
 
         if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index be0afbb..3efd049 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -229,9 +229,6 @@
     private ActivityRecord mLastScreenshotActivity = null;
     private Bitmap mLastScreenshotBitmap = null;
 
-    int mThumbnailWidth = -1;
-    int mThumbnailHeight = -1;
-
     int mCurrentUser;
 
     final int mStackId;
@@ -355,10 +352,6 @@
         mWindowManager = mService.mWindowManager;
         mStackId = activityContainer.mStackId;
         mCurrentUser = mService.mCurrentUserId;
-        // Get the activity screenshot thumbnail dimensions
-        Resources res = mService.mContext.getResources();
-        mThumbnailWidth = mService.mThumbnailWidth;
-        mThumbnailHeight = mService.mThumbnailHeight;
     }
 
     /**
@@ -773,8 +766,8 @@
             return null;
         }
 
-        int w = mThumbnailWidth;
-        int h = mThumbnailHeight;
+        int w = mService.mThumbnailWidth;
+        int h = mService.mThumbnailHeight;
         if (w > 0) {
             if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
                     || mLastScreenshotActivity.state == ActivityState.RESUMED
@@ -1492,6 +1485,9 @@
             ActivityOptions.abort(options);
             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+
+            // Make sure to notify Keyguard as well if it is waiting for an activity to be drawn.
+            mStackSupervisor.notifyActivityDrawnForKeyguard();
             return false;
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9b32b65..1d2f7a9 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1543,6 +1543,15 @@
         final Intent intent = r.intent;
         final int callingUid = r.launchedFromUid;
 
+        // In some flows in to this function, we retrieve the task record and hold on to it
+        // without a lock before calling back in to here...  so the task at this point may
+        // not actually be in recents.  Check for that, and if it isn't in recents just
+        // consider it invalid.
+        if (inTask != null && !inTask.inRecents) {
+            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
+            inTask = null;
+        }
+
         final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
         final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
         final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -1686,32 +1695,50 @@
         // If the caller is not coming from another activity, but has given us an
         // explicit task into which they would like us to launch the new activity,
         // then let's see about doing that.
-        if (sourceRecord == null && inTask != null && inTask.stack != null && inTask.inRecents) {
+        if (sourceRecord == null && inTask != null && inTask.stack != null) {
+            final Intent baseIntent = inTask.getBaseIntent();
+            final ActivityRecord root = inTask.getRootActivity();
+            if (baseIntent == null) {
+                ActivityOptions.abort(options);
+                throw new IllegalArgumentException("Launching into task without base intent: "
+                        + inTask);
+            }
+
             // If this task is empty, then we are adding the first activity -- it
             // determines the root, and must be launching as a NEW_TASK.
-            if (inTask.getRootActivity() == null) {
-                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
-                        && !launchSingleInstance && !launchSingleTask) {
-                    throw new IllegalStateException("Caller has inTask " + inTask
-                            + " but target is not a new task");
-                } else if (inTask.getBaseIntent() == null || !intent.getComponent().equals(
-                        inTask.getBaseIntent().getComponent())) {
-                    throw new IllegalStateException("Caller requested " + inTask + " is component "
-                            + inTask.getBaseIntent() + " but starting " + intent);
+            if (launchSingleInstance || launchSingleTask) {
+                if (!baseIntent.getComponent().equals(r.intent.getComponent())) {
+                    ActivityOptions.abort(options);
+                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
+                            + r + " into different task " + inTask);
                 }
+                if (root != null) {
+                    ActivityOptions.abort(options);
+                    throw new IllegalArgumentException("Caller with inTask " + inTask
+                            + " has root " + root + " but target is singleInstance/Task");
+                }
+            }
+
+            // If task is empty, then adopt the interesting intent launch flags in to the
+            // activity being started.
+            if (root == null) {
+                final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+                        | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
+                launchFlags = (launchFlags&~flagsOfInterest)
+                        | (baseIntent.getFlags()&flagsOfInterest);
+                intent.setFlags(launchFlags);
                 inTask.setIntent(r);
 
             // If the task is not empty, then we are going to add the new activity on top
             // of the task, so it can not be launching as a new task.
-            } else {
-                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
-                        || launchSingleInstance || launchSingleTask) {
-                    throw new IllegalStateException("Caller has inTask " + inTask
-                            + " but target is a new task");
-                }
+            } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+                ActivityOptions.abort(options);
+                throw new IllegalStateException("Caller has inTask " + inTask
+                        + " but target is a new task");
             }
-            sourceStack = inTask.stack;
             reuseTask = inTask;
+            addingToTask = true;
         } else {
             inTask = null;
         }
@@ -1724,10 +1751,11 @@
         if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                 (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                 || launchSingleInstance || launchSingleTask) {
-            // If bring to front is requested, and no result is requested, and
+            // If bring to front is requested, and no result is requested and we have not
+            // been given an explicit task to launch in to, and
             // we can find a task that was started with this same
             // component, then instead of launching bring that one to the front.
-            if (r.resultTo == null) {
+            if (inTask == null && r.resultTo == null) {
                 // See if there is a task to bring to the front.  If this is
                 // a SINGLE_INSTANCE activity, there can be one and only one
                 // instance of it in the history, and it is always in its own
@@ -1957,13 +1985,8 @@
                 Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                 return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
-            if (inTask == null) {
-                // If we have an incoming task, we are just going to use that.
-                newTask = true;
-                targetStack = adjustStackFocus(r, newTask);
-            } else {
-                targetStack = inTask.stack;
-            }
+            newTask = true;
+            targetStack = adjustStackFocus(r, newTask);
             if (!launchTaskBehind) {
                 targetStack.moveToFront();
             }
@@ -2048,8 +2071,27 @@
                 return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
             targetStack = inTask.stack;
-            targetStack.moveToFront();
+            targetStack.moveTaskToFrontLocked(inTask, r, options);
             mWindowManager.moveTaskToTop(targetStack.topTask().taskId);
+
+            // Check whether we should actually launch the new activity in to the task,
+            // or just reuse the current activity on top.
+            ActivityRecord top = inTask.getTopActivity();
+            if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
+                if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
+                        || launchSingleTop || launchSingleTask) {
+                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
+                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
+                        // We don't need to start a new activity, and
+                        // the client said not to do anything if that
+                        // is the case, so this is it!
+                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
+                    }
+                    top.deliverNewIntentLocked(callingUid, r.intent);
+                    return ActivityManager.START_DELIVERED_TO_TOP;
+                }
+            }
+
             r.setTask(inTask, null);
             if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                     + " in explicit task " + r.task);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 77c324f..1287dce 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -21,6 +21,7 @@
 import java.nio.ByteBuffer;
 
 import android.app.ActivityManager;
+import android.os.SystemClock;
 import com.android.internal.util.MemInfoReader;
 import com.android.server.wm.WindowManagerService;
 
@@ -528,12 +529,18 @@
         if (amt == UNKNOWN_ADJ)
             return;
 
+        long start = SystemClock.elapsedRealtime();
         ByteBuffer buf = ByteBuffer.allocate(4 * 4);
         buf.putInt(LMK_PROCPRIO);
         buf.putInt(pid);
         buf.putInt(uid);
         buf.putInt(amt);
         writeLmkd(buf);
+        long now = SystemClock.elapsedRealtime();
+        if ((now-start) > 250) {
+            Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
+                    + " = " + amt);
+        }
     }
 
     /*
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 4b812cf..aa1310d 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -248,6 +248,11 @@
     static final int DISABLED = 0;
     static final int ENABLED = 1;
 
+    // Property name for the local device configurations.
+    // TODO(OEM): OEM should provide this property, and the value is the comma separated integer
+    //     values which denotes the device type in HDMI Spec 1.4.
+    static final String PROPERTY_DEVICE_TYPE = "ro.hdmi.device_type";
+
     // --------------------------------------------------
     // MHL sub command message types.
     static final int MHL_MSG_MSGE  = 0x02;
@@ -275,11 +280,6 @@
     static final int MHL_CBUS_MODE_ECBUS_S = 2;
     static final int MHL_CBUS_MODE_ECBUS_D = 3;
 
-    // Property name for the local device configurations.
-    // TODO(OEM): OEM should provide this property, and the value is the comma separated integer
-    //     values which denotes the device type in HDMI Spec 1.4.
-    static final String PROPERTY_DEVICE_TYPE = "ro.hdmi.device_type";
-
     // MHL RCPE messages
     static final int MHL_RCPE_NO_ERROR = 0x00;
     static final int MHL_RCPE_INEFFECTIVE_KEYCODE = 0x01;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 827b3ed..bb22b4d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -23,6 +23,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Predicate;
 import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -30,6 +31,8 @@
 
 import libcore.util.EmptyArray;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -446,7 +449,7 @@
                         allocated.add(address);
                     }
                 }
-                mIoThreadLogger.debug("DevicePollingResult:" + allocated);
+                mIoThreadLogger.debug("[P]:Allocated Address=" + allocated);
                 if (callback != null) {
                     runOnServiceThread(new Runnable() {
                         @Override
@@ -548,7 +551,7 @@
         runOnIoThread(new Runnable() {
             @Override
             public void run() {
-                mIoThreadLogger.debug("SendCommand:" + cecMessage);
+                mIoThreadLogger.debug("[S]:" + cecMessage);
                 byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
                 int i = 0;
                 int errorCode = Constants.SEND_RESULT_SUCCESS;
@@ -583,7 +586,7 @@
     private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
         assertRunOnServiceThread();
         HdmiCecMessage command = HdmiCecMessageBuilder.of(srcAddress, dstAddress, body);
-        mServiceThreadLogger.debug("ReceiveCommand:" + command);
+        mServiceThreadLogger.debug("[R]:" + command);
         onReceiveCommand(command);
     }
 
@@ -598,6 +601,15 @@
         mService.onHotplug(port, connected);
     }
 
+    void dump(final IndentingPrintWriter pw) {
+        for (int i = 0; i < mLocalDevices.size(); ++i) {
+            pw.println("HdmiCecLocalDevice #" + i + ":");
+            pw.increaseIndent();
+            mLocalDevices.valueAt(i).dump(pw);
+            pw.decreaseIndent();
+        }
+    }
+
     private static native long nativeInit(HdmiCecController handler, MessageQueue messageQueue);
     private static native int nativeSendCecCommand(long controllerPtr, int srcAddress,
             int dstAddress, byte[] body);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index 26d2cde..85f5be2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -43,6 +43,9 @@
  */
 abstract class HdmiCecFeatureAction {
     private static final String TAG = "HdmiCecFeatureAction";
+    // As all actions run in the same thread (service thread), it's fine to have single logger.
+    // TODO: create global logger for each threads and use them.
+    protected static final HdmiLogger DLOGGER = new HdmiLogger(TAG);
 
     // Timer handler message used for timeout event
     protected static final int MSG_TIMEOUT = 100;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index a12e4fc..38addba 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -28,6 +28,7 @@
 import android.view.KeyEvent;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 
 import java.util.ArrayList;
@@ -97,6 +98,17 @@
         public int hashCode() {
             return logicalAddress * 29 + physicalAddress;
         }
+        @Override
+        public String toString() {
+            StringBuffer s = new StringBuffer();
+            String logicalAddressString = (logicalAddress == Constants.ADDR_INVALID)
+                    ? "invalid" : String.format("0x%02x", logicalAddress);
+            s.append("logical_address: ").append(logicalAddressString);
+            String physicalAddressString = (physicalAddress == Constants.INVALID_PHYSICAL_ADDRESS)
+                    ? "invalid" : String.format("0x%04x", physicalAddress);
+            s.append(", physical_address: ").append(physicalAddressString);
+            return s.toString();
+        }
     }
     // Logical address of the active source.
     @GuardedBy("mLock")
@@ -793,4 +805,16 @@
     protected void sendKeyEvent(int keyCode, boolean isPressed) {
         Slog.w(TAG, "sendKeyEvent not implemented");
     }
+
+    /**
+     * Dump internal status of HdmiCecLocalDevice object.
+     */
+    protected void dump(final IndentingPrintWriter pw) {
+        pw.println("mDeviceType: " + mDeviceType);
+        pw.println("mAddress: " + mAddress);
+        pw.println("mPreferredAddress: " + mPreferredAddress);
+        pw.println("mDeviceInfo: " + mDeviceInfo);
+        pw.println("mActiveSource: " + mActiveSource);
+        pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 5a2fa9c..6603a71 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -23,6 +23,7 @@
 import android.os.SystemProperties;
 import android.util.Slog;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 
 /**
@@ -219,4 +220,10 @@
         mIsActiveSource = false;
         checkIfPendingActionsCleared();
     }
+
+    @Override
+    protected void dump(final IndentingPrintWriter pw) {
+        super.dump(pw);
+        pw.println("mIsActiveSource: " + mIsActiveSource);
+    }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index cd56cfc..1ab8069 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -45,6 +45,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
@@ -1610,4 +1611,16 @@
 
         invokeDeviceEventListener(newInfo, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE);
     }
+
+    @Override
+    protected void dump(final IndentingPrintWriter pw) {
+        super.dump(pw);
+        pw.println("mArcEstablished: " + mArcEstablished);
+        pw.println("mArcFeatureEnabled: " + mArcFeatureEnabled);
+        pw.println("mSystemAudioActivated: " + mSystemAudioActivated);
+        pw.println("mSystemAudioMute: " + mSystemAudioMute);
+        pw.println("mAutoDeviceOff: " + mAutoDeviceOff);
+        pw.println("mAutoWakeup: " + mAutoWakeup);
+        pw.println("mSkipRoutingControl: " + mSkipRoutingControl);
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index fcccfc0..d13e1de 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -67,6 +67,7 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
@@ -75,6 +76,8 @@
 
 import libcore.util.EmptyArray;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -179,11 +182,6 @@
     private final ArrayList<VendorCommandListenerRecord> mVendorCommandListenerRecords =
             new ArrayList<>();
 
-    // List of records for MHL Scratchpad command listener to handle the caller killed in action.
-    @GuardedBy("mLock")
-    private final ArrayList<HdmiMhlScratchpadCommandListenerRecord>
-            mScratchpadCommandListenerRecords = new ArrayList<>();
-
     @GuardedBy("mLock")
     private InputChangeListenerRecord mInputChangeListenerRecord;
 
@@ -201,13 +199,6 @@
     @GuardedBy("mLock")
     private boolean mProhibitMode;
 
-    // Set to true while the input change by MHL is allowed.
-    @GuardedBy("mLock")
-    private boolean mMhlInputChangeEnabled;
-
-    @GuardedBy("mLock")
-    private List<HdmiDeviceInfo> mMhlDevices;
-
     // List of records for system audio mode change to handle the the caller killed in action.
     private final ArrayList<SystemAudioModeChangeListenerRecord>
             mSystemAudioModeChangeListenerRecords = new ArrayList<>();
@@ -223,9 +214,6 @@
     @Nullable
     private HdmiCecController mCecController;
 
-    @Nullable
-    private HdmiMhlController mMhlController;
-
     // HDMI port information. Stored in the unmodifiable list to keep the static information
     // from being modified.
     private List<HdmiPortInfo> mPortInfo;
@@ -256,8 +244,23 @@
     @ServiceThreadOnly
     private int mActivePortId = Constants.INVALID_PORT_ID;
 
-    // Last input port before switching to the MHL port by way of incoming request RAP[ContentOn].
-    // Should switch back to this port when the device sends RAP[ContentOff].
+    // Set to true while the input change by MHL is allowed.
+    @GuardedBy("mLock")
+    private boolean mMhlInputChangeEnabled;
+
+    // List of records for MHL Scratchpad command listener to handle the caller killed in action.
+    @GuardedBy("mLock")
+    private final ArrayList<HdmiMhlScratchpadCommandListenerRecord>
+            mScratchpadCommandListenerRecords = new ArrayList<>();
+
+    @GuardedBy("mLock")
+    private List<HdmiDeviceInfo> mMhlDevices;
+
+    @Nullable
+    private HdmiMhlController mMhlController;
+
+    // Last input port before switching to the MHL port. Should switch back to this port
+    // when the mobile device sends the request one touch play with off.
     // Gets invalidated if we go to other port/input.
     @ServiceThreadOnly
     private int mLastInputMhl = Constants.INVALID_PORT_ID;
@@ -304,16 +307,17 @@
         }
 
         mMhlController = HdmiMhlController.create(this);
-        if (mMhlController == null) {
+        if (!mMhlController.isReady()) {
             Slog.i(TAG, "Device does not support MHL-control.");
         }
-        initPortInfo();
         mMhlDevices = Collections.emptyList();
+
+        initPortInfo();
         mMessageValidator = new HdmiCecMessageValidator(this);
         publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
 
         // Register broadcast receiver for power state change.
-        if (mCecController != null || mMhlController != null) {
+        if (mCecController != null) {
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_SCREEN_OFF);
             filter.addAction(Intent.ACTION_SCREEN_ON);
@@ -378,9 +382,7 @@
                     setMhlInputChangeEnabled(enabled);
                     break;
                 case Global.MHL_POWER_CHARGE_ENABLED:
-                    if (mMhlController != null) {
-                        mMhlController.setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled));
-                    }
+                    mMhlController.setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled));
                     break;
             }
         }
@@ -484,30 +486,30 @@
         mPortInfoMap = new UnmodifiableSparseArray<>(portInfoMap);
         mPortDeviceMap = new UnmodifiableSparseArray<>(portDeviceMap);
 
-        if (mMhlController == null) {
+        HdmiPortInfo[] mhlPortInfo = mMhlController.getPortInfos();
+        ArraySet<Integer> mhlSupportedPorts = new ArraySet<Integer>(mhlPortInfo.length);
+        for (HdmiPortInfo info : mhlPortInfo) {
+            if (info.isMhlSupported()) {
+                mhlSupportedPorts.add(info.getId());
+            }
+        }
+
+        // Build HDMI port info list with CEC port info plus MHL supported flag. We can just use
+        // cec port info if we do not have have port that supports MHL.
+        if (mhlSupportedPorts.isEmpty()) {
             mPortInfo = Collections.unmodifiableList(Arrays.asList(cecPortInfo));
             return;
-        } else {
-            HdmiPortInfo[] mhlPortInfo = mMhlController.getPortInfos();
-            ArraySet<Integer> mhlSupportedPorts = new ArraySet<Integer>(mhlPortInfo.length);
-            for (HdmiPortInfo info : mhlPortInfo) {
-                if (info.isMhlSupported()) {
-                    mhlSupportedPorts.add(info.getId());
-                }
-            }
-
-            // Build HDMI port info list with CEC port info plus MHL supported flag.
-            ArrayList<HdmiPortInfo> result = new ArrayList<>(cecPortInfo.length);
-            for (HdmiPortInfo info : cecPortInfo) {
-                if (mhlSupportedPorts.contains(info.getId())) {
-                    result.add(new HdmiPortInfo(info.getId(), info.getType(), info.getAddress(),
-                            info.isCecSupported(), true, info.isArcSupported()));
-                } else {
-                    result.add(info);
-                }
-            }
-            mPortInfo = Collections.unmodifiableList(result);
         }
+        ArrayList<HdmiPortInfo> result = new ArrayList<>(cecPortInfo.length);
+        for (HdmiPortInfo info : cecPortInfo) {
+            if (mhlSupportedPorts.contains(info.getId())) {
+                result.add(new HdmiPortInfo(info.getId(), info.getType(), info.getAddress(),
+                        info.isCecSupported(), true, info.isArcSupported()));
+            } else {
+                result.add(info);
+            }
+        }
+        mPortInfo = Collections.unmodifiableList(result);
     }
 
     List<HdmiPortInfo> getPortInfo() {
@@ -652,18 +654,6 @@
         sendCecCommand(command, null);
     }
 
-    @ServiceThreadOnly
-    void sendMhlSubcommand(int portId, HdmiMhlSubcommand command) {
-        assertRunOnServiceThread();
-        sendMhlSubcommand(portId, command, null);
-    }
-
-    @ServiceThreadOnly
-    void sendMhlSubcommand(int portId, HdmiMhlSubcommand command, SendMessageCallback callback) {
-        assertRunOnServiceThread();
-        mMhlController.sendSubcommand(portId, command, callback);
-    }
-
     /**
      * Send <Feature Abort> command on the given CEC message if possible.
      * If the aborted message is invalid, then it wont send the message.
@@ -796,6 +786,18 @@
     }
 
     @ServiceThreadOnly
+    void sendMhlSubcommand(int portId, HdmiMhlSubcommand command) {
+        assertRunOnServiceThread();
+        sendMhlSubcommand(portId, command, null);
+    }
+
+    @ServiceThreadOnly
+    void sendMhlSubcommand(int portId, HdmiMhlSubcommand command, SendMessageCallback callback) {
+        assertRunOnServiceThread();
+        mMhlController.sendSubcommand(portId, command, callback);
+    }
+
+    @ServiceThreadOnly
     boolean handleMhlSubcommand(int portId, HdmiMhlSubcommand message) {
         assertRunOnServiceThread();
 
@@ -895,6 +897,19 @@
         return mMhlDevices;
     }
 
+    private class HdmiMhlScratchpadCommandListenerRecord implements IBinder.DeathRecipient {
+        private final IHdmiMhlScratchpadCommandListener mListener;
+
+        public HdmiMhlScratchpadCommandListenerRecord(IHdmiMhlScratchpadCommandListener listener) {
+            mListener = listener;
+        }
+
+        @Override
+        public void binderDied() {
+            mScratchpadCommandListenerRecords.remove(this);
+        }
+    }
+
     // Record class that monitors the event of the caller of being killed. Used to clean up
     // the listener list and record list accordingly.
     private final class HotplugEventListenerRecord implements IBinder.DeathRecipient {
@@ -974,19 +989,6 @@
         }
     }
 
-    private class HdmiMhlScratchpadCommandListenerRecord implements IBinder.DeathRecipient {
-        private final IHdmiMhlScratchpadCommandListener mListener;
-
-        public HdmiMhlScratchpadCommandListenerRecord(IHdmiMhlScratchpadCommandListener listener) {
-            mListener = listener;
-        }
-
-        @Override
-        public void binderDied() {
-            mScratchpadCommandListenerRecords.remove(this);
-        }
-    }
-
     private void enforceAccessPermission() {
         getContext().enforceCallingOrSelfPermission(PERMISSION, TAG);
     }
@@ -1039,20 +1041,18 @@
                         invokeCallback(callback, HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE);
                         return;
                     }
-                    if (mMhlController != null) {
-                        HdmiMhlLocalDevice device = mMhlController.getLocalDeviceById(deviceId);
-                        if (device != null) {
-                            if (device.getPortId() == tv.getActivePortId()) {
-                                invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
-                                return;
-                            }
-                            // Upon selecting MHL device, we send RAP[Content On] to wake up
-                            // the connected mobile device, start routing control to switch ports.
-                            // callback is handled by MHL action.
-                            device.turnOn(callback);
-                            tv.doManualPortSwitching(device.getInfo().getPortId(), null);
+                    HdmiMhlLocalDevice device = mMhlController.getLocalDeviceById(deviceId);
+                    if (device != null) {
+                        if (device.getPortId() == tv.getActivePortId()) {
+                            invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
                             return;
                         }
+                        // Upon selecting MHL device, we send RAP[Content On] to wake up
+                        // the connected mobile device, start routing control to switch ports.
+                        // callback is handled by MHL action.
+                        device.turnOn(callback);
+                        tv.doManualPortSwitching(device.getInfo().getPortId(), null);
+                        return;
                     }
                     tv.deviceSelect(deviceId, callback);
                 }
@@ -1086,12 +1086,10 @@
             runOnServiceThread(new Runnable() {
                 @Override
                 public void run() {
-                    if (mMhlController != null) {
-                        HdmiMhlLocalDevice device = mMhlController.getLocalDevice(mActivePortId);
-                        if (device != null) {
-                            device.sendKeyEvent(keyCode, isPressed);
-                            return;
-                        }
+                    HdmiMhlLocalDevice device = mMhlController.getLocalDevice(mActivePortId);
+                    if (device != null) {
+                        device.sendKeyEvent(keyCode, isPressed);
+                        return;
                     }
                     if (mCecController != null) {
                         HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(deviceType);
@@ -1380,10 +1378,6 @@
             runOnServiceThread(new Runnable() {
                 @Override
                 public void run() {
-                    if (mMhlController == null) {
-                        Slog.w(TAG, "No Mhl controller available.");
-                        return;
-                    }
                     if (!isControlEnabled()) {
                         Slog.w(TAG, "Hdmi control is disabled.");
                         return ;
@@ -1404,6 +1398,28 @@
             enforceAccessPermission();
             HdmiControlService.this.addHdmiMhlScratchpadCommandListener(listener);
         }
+
+        @Override
+        protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
+
+            pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
+            pw.println("mProhibitMode: " + mProhibitMode);
+            if (mCecController != null) {
+                pw.println("mCecController: ");
+                pw.increaseIndent();
+                mCecController.dump(pw);
+                pw.decreaseIndent();
+            }
+            pw.println("mPortInfo: ");
+            pw.increaseIndent();
+            for (HdmiPortInfo hdmiPortInfo : mPortInfo) {
+                pw.println("- " + hdmiPortInfo);
+            }
+            pw.decreaseIndent();
+            pw.println("mPowerStatus: " + mPowerStatus);
+        }
     }
 
     @ServiceThreadOnly
@@ -1775,9 +1791,7 @@
             }
         }
 
-        if (mMhlController != null) {
-            mMhlController.clearAllLocalDevices();
-        }
+        mMhlController.clearAllLocalDevices();
     }
 
     @ServiceThreadOnly
@@ -1887,9 +1901,7 @@
 
         int value = toInt(enabled);
         mCecController.setOption(OPTION_CEC_ENABLE, value);
-        if (mMhlController != null) {
-            mMhlController.setOption(OPTION_MHL_ENABLE, value);
-        }
+        mMhlController.setOption(OPTION_MHL_ENABLE, value);
 
         synchronized (mLock) {
             mHdmiControlEnabled = enabled;
@@ -1955,7 +1967,7 @@
         tv().setActivePortId(portId);
 
         // The port is either the MHL-enabled port where the mobile device is connected, or
-        // the last port to go back to when RAP[ContentOff] is received. Note that the last port
+        // the last port to go back to when turnoff command is received. Note that the last port
         // may not be the MHL-enabled one. In this case the device info to be passed to
         // input change listener should be the one describing the corresponding HDMI port.
         HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId);
@@ -1966,9 +1978,7 @@
     }
 
    void setMhlInputChangeEnabled(boolean enabled) {
-        if (mMhlController != null) {
-            mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
-        }
+       mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
 
         synchronized (mLock) {
             mMhlInputChangeEnabled = enabled;
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index ee9379d..c7add75 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -42,7 +42,7 @@
     private final String mTag;
 
     HdmiLogger(String tag) {
-        mTag = tag;
+        mTag = "HDMI:" + tag;
     }
 
     void warning(String logMessage) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index ac2c7b9..d15ffb0 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -73,9 +73,9 @@
 
     // Seq #27
     protected void sendSystemAudioModeRequest() {
-        mState = STATE_CHECK_ROUTING_IN_PRGRESS;
         List<RoutingControlAction> routingActions = getActions(RoutingControlAction.class);
         if (!routingActions.isEmpty()) {
+            mState = STATE_CHECK_ROUTING_IN_PRGRESS;
             // Should have only one Routing Control Action
             RoutingControlAction routingAction = routingActions.get(0);
             routingAction.addOnFinishedCallback(this, new Runnable() {
@@ -97,20 +97,21 @@
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error == Constants.SEND_RESULT_SUCCESS) {
-                    mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
-                    addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
-                } else {
+                if (error != Constants.SEND_RESULT_SUCCESS) {
+                    DLOGGER.debug("Failed to send <System Audio Mode Request>:" + error);
                     setSystemAudioMode(false);
                     finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
                 }
             }
         });
+        mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
+        addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
     }
 
     private void handleSendSystemAudioModeRequestTimeout() {
         if (!mTargetAudioStatus  // Don't retry for Off case.
                 || mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
+            DLOGGER.debug("[T]:wait for <Set System Audio Mode>.");
             setSystemAudioMode(false);
             finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
             return;
@@ -129,6 +130,7 @@
                 if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
                         && (cmd.getParams()[0] & 0xFF)
                                 == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
+                    DLOGGER.debug("Failed to start system audio mode request.");
                     setSystemAudioMode(false);
                     finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
                     return true;
@@ -143,6 +145,7 @@
                     startAudioStatusAction();
                     return true;
                 } else {
+                    DLOGGER.debug("Unexpected system audio mode request:" + receivedStatus);
                     // Unexpected response, consider the request is newly initiated by AVR.
                     // To return 'false' will initiate new SystemAudioActionFromAvr by the control
                     // service.
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 978a9f4..0da2cfa 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -23,6 +23,7 @@
 import android.content.pm.ParceledListSlice;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
+import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -441,7 +442,7 @@
 
     private String getShortMetadataString() {
         int fields = mMetadata == null ? 0 : mMetadata.size();
-        MediaMetadata.Description description = mMetadata == null ? null : mMetadata
+        MediaDescription description = mMetadata == null ? null : mMetadata
                 .getDescription();
         return "size=" + fields + ", description=" + description;
     }
@@ -820,9 +821,9 @@
             }
         }
 
-        public void playUri(Uri uri, Bundle extras) {
+        public void playFromMediaId(String mediaId, Bundle extras) {
             try {
-                mCb.onPlayUri(uri, extras);
+                mCb.onPlayFromMediaId(mediaId, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in playUri.", e);
             }
@@ -1042,8 +1043,8 @@
         }
 
         @Override
-        public void playUri(Uri uri, Bundle extras) throws RemoteException {
-            mSessionCb.playUri(uri, extras);
+        public void playFromMediaId(String mediaId, Bundle extras) throws RemoteException {
+            mSessionCb.playFromMediaId(mediaId, extras);
         }
 
         @Override
@@ -1052,7 +1053,7 @@
         }
 
         @Override
-        public void skipToTrack(long id) {
+        public void skipToQueueItem(long id) {
             mSessionCb.skipToTrack(id);
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8c0d2c9..fc1b746 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -57,7 +57,6 @@
 import android.os.IInterface;
 import android.os.Looper;
 import android.os.Message;
-import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -127,6 +126,7 @@
     static final int MESSAGE_RANKING_CONFIG_CHANGE = 5;
     static final int MESSAGE_SEND_RANKING_UPDATE = 6;
     static final int MESSAGE_LISTENER_HINTS_CHANGED = 7;
+    static final int MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED = 8;
 
     static final int LONG_DELAY = 3500; // 3.5 seconds
     static final int SHORT_DELAY = 2000; // 2 seconds
@@ -178,6 +178,7 @@
     private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
     private ComponentName mEffectsSuppressor;
     private int mListenerHints;  // right now, all hints are global
+    private int mInterruptionFilter;  // current ZEN mode as communicated to listeners
 
     // for enabling and disabling notification pulse behavior
     private boolean mScreenOn = true;
@@ -806,7 +807,7 @@
             @Override
             void onZenModeChanged() {
                 synchronized(mNotificationList) {
-                    updateListenerHintsLocked();
+                    updateInterruptionFilterLocked();
                 }
             }
         });
@@ -938,8 +939,7 @@
     }
 
     private void updateListenerHintsLocked() {
-        final int hints = (mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS) |
-                mZenModeHelper.getZenModeListenerHint();
+        final int hints = mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS;
         if (hints == mListenerHints) return;
         mListenerHints = hints;
         scheduleListenerHintsChanged(hints);
@@ -954,6 +954,13 @@
                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
     }
 
+    private void updateInterruptionFilterLocked() {
+        int interruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
+        if (interruptionFilter == mInterruptionFilter) return;
+        mInterruptionFilter = interruptionFilter;
+        scheduleInterruptionFilterChanged(interruptionFilter);
+    }
+
     private final IBinder mService = new INotificationManager.Stub() {
         // Toasts
         // ============================================================================
@@ -1318,7 +1325,6 @@
                     } else {
                         mListenersDisablingEffects.remove(info);
                     }
-                    mZenModeHelper.requestFromListener(hints);
                     updateListenerHintsLocked();
                     updateEffectsSuppressorLocked();
                 }
@@ -1335,6 +1341,29 @@
         }
 
         @Override
+        public void requestInterruptionFilterFromListener(INotificationListener token,
+                int interruptionFilter) throws RemoteException {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mNotificationList) {
+                    mListeners.checkServiceTokenLocked(token);
+                    mZenModeHelper.requestFromListener(interruptionFilter);
+                    updateInterruptionFilterLocked();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public int getInterruptionFilterFromListener(INotificationListener token)
+                throws RemoteException {
+            synchronized (mNotificationLight) {
+                return mInterruptionFilter;
+            }
+        }
+
+        @Override
         public ZenModeConfig getZenModeConfig() {
             enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
             return mZenModeHelper.getConfig();
@@ -2058,12 +2087,26 @@
         mHandler.obtainMessage(MESSAGE_LISTENER_HINTS_CHANGED, state, 0).sendToTarget();
     }
 
+    private void scheduleInterruptionFilterChanged(int listenerInterruptionFilter) {
+        mHandler.removeMessages(MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED);
+        mHandler.obtainMessage(
+                MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED,
+                listenerInterruptionFilter,
+                0).sendToTarget();
+    }
+
     private void handleListenerHintsChanged(int hints) {
         synchronized (mNotificationList) {
             mListeners.notifyListenerHintsChangedLocked(hints);
         }
     }
 
+    private void handleListenerInterruptionFilterChanged(int interruptionFilter) {
+        synchronized (mNotificationList) {
+            mListeners.notifyInterruptionFilterChanged(interruptionFilter);
+        }
+    }
+
     private final class WorkerHandler extends Handler
     {
         @Override
@@ -2083,6 +2126,9 @@
                 case MESSAGE_LISTENER_HINTS_CHANGED:
                     handleListenerHintsChanged(msg.arg1);
                     break;
+                case MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED:
+                    handleListenerInterruptionFilterChanged(msg.arg1);
+                    break;
             }
         }
 
@@ -2701,6 +2747,20 @@
             }
         }
 
+        public void notifyInterruptionFilterChanged(final int interruptionFilter) {
+            for (final ManagedServiceInfo serviceInfo : mServices) {
+                if (!serviceInfo.isEnabledForCurrentProfiles()) {
+                    continue;
+                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        notifyInterruptionFilterChanged(serviceInfo, interruptionFilter);
+                    }
+                });
+            }
+        }
+
         private void notifyPosted(final ManagedServiceInfo info,
                 final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
             final INotificationListener listener = (INotificationListener)info.service;
@@ -2743,6 +2803,16 @@
             }
         }
 
+        private void notifyInterruptionFilterChanged(ManagedServiceInfo info,
+                int interruptionFilter) {
+            final INotificationListener listener = (INotificationListener) info.service;
+            try {
+                listener.onInterruptionFilterChanged(interruptionFilter);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "unable to notify listener (interruption filter): " + listener, ex);
+            }
+        }
+
         private boolean isListenerPackage(String packageName) {
             if (packageName == null) {
                 return false;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 0b93690..7a5336b 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -115,35 +115,35 @@
         mAudioManager = audioManager;
     }
 
-    public int getZenModeListenerHint() {
-        switch(mZenMode) {
+    public int getZenModeListenerInterruptionFilter() {
+        switch (mZenMode) {
             case Global.ZEN_MODE_OFF:
-                return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_ALL;
+                return NotificationListenerService.INTERRUPTION_FILTER_ALL;
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
-                return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_PRIORITY;
+                return NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
-                return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_NONE;
+                return NotificationListenerService.INTERRUPTION_FILTER_NONE;
             default:
                 return 0;
         }
     }
 
-    private static int zenFromListenerHint(int hints, int defValue) {
-        final int level = hints & NotificationListenerService.HOST_INTERRUPTION_LEVEL_MASK;
-        switch(level) {
-            case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_ALL:
+    private static int zenModeFromListenerInterruptionFilter(int listenerInterruptionFilter,
+            int defValue) {
+        switch (listenerInterruptionFilter) {
+            case NotificationListenerService.INTERRUPTION_FILTER_ALL:
                 return Global.ZEN_MODE_OFF;
-            case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_PRIORITY:
+            case NotificationListenerService.INTERRUPTION_FILTER_PRIORITY:
                 return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-            case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_NONE:
+            case NotificationListenerService.INTERRUPTION_FILTER_NONE:
                 return Global.ZEN_MODE_NO_INTERRUPTIONS;
             default:
                 return defValue;
         }
     }
 
-    public void requestFromListener(int hints) {
-        final int newZen = zenFromListenerHint(hints, -1);
+    public void requestFromListener(int interruptionFilter) {
+        final int newZen = zenModeFromListenerInterruptionFilter(interruptionFilter, -1);
         if (newZen != -1) {
             setZenMode(newZen, "listener");
         }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 694669c..ca11862 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -224,10 +224,6 @@
         }
     }
 
-    public int pruneDexCache(String cacheSubDir) {
-        return mInstaller.execute("prunedexcache " + cacheSubDir);
-    }
-
     public int freeCache(long freeStorageSize) {
         StringBuilder builder = new StringBuilder("freecache");
         builder.append(' ');
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5093f97..2cb9077 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1497,29 +1497,6 @@
                 }
             }
 
-            if (didDexOptLibraryOrTool) {
-                // If we dexopted a library or tool, then something on the system has
-                // changed. Consider this significant, and wipe away all other
-                // existing dexopt files to ensure we don't leave any dangling around.
-                //
-                // TODO: This should be revisited because it isn't as good an indicator
-                // as it used to be. It used to include the boot classpath but at some point
-                // DexFile.isDexOptNeeded started returning false for the boot
-                // class path files in all cases. It is very possible in a
-                // small maintenance release update that the library and tool
-                // jars may be unchanged but APK could be removed resulting in
-                // unused dalvik-cache files.
-                for (String dexCodeInstructionSet : dexCodeInstructionSets) {
-                    mInstaller.pruneDexCache(dexCodeInstructionSet);
-                }
-
-                // Additionally, delete all dex files from the root directory
-                // since there shouldn't be any there anyway, unless we're upgrading
-                // from an older OS version or a build that contained the "old" style
-                // flat scheme.
-                mInstaller.pruneDexCache(".");
-            }
-
             // Collect vendor overlay packages.
             // (Do this before scanning any apps.)
             // For security and version matching reason, only consider
@@ -11051,34 +11028,34 @@
             Slog.w(TAG, "Attempt to delete null packageName.");
             return false;
         }
-        PackageParser.Package p;
+        PackageParser.Package pkg;
         boolean dataOnly = false;
         final int appId;
         synchronized (mPackages) {
-            p = mPackages.get(packageName);
-            if (p == null) {
+            pkg = mPackages.get(packageName);
+            if (pkg == null) {
                 dataOnly = true;
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if ((ps == null) || (ps.pkg == null)) {
                     Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
                     return false;
                 }
-                p = ps.pkg;
+                pkg = ps.pkg;
             }
             if (!dataOnly) {
                 // need to check this only for fully installed applications
-                if (p == null) {
+                if (pkg == null) {
                     Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
                     return false;
                 }
-                final ApplicationInfo applicationInfo = p.applicationInfo;
+                final ApplicationInfo applicationInfo = pkg.applicationInfo;
                 if (applicationInfo == null) {
                     Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
                     return false;
                 }
             }
-            if (p != null && p.applicationInfo != null) {
-                appId = p.applicationInfo.uid;
+            if (pkg != null && pkg.applicationInfo != null) {
+                appId = pkg.applicationInfo.uid;
             } else {
                 appId = -1;
             }
@@ -11090,6 +11067,19 @@
             return false;
         }
         removeKeystoreDataIfNeeded(userId, appId);
+
+        // Create a native library symlink only if we have native libraries
+        // and if the native libraries are 32 bit libraries. We do not provide
+        // this symlink for 64 bit libraries.
+        if (pkg != null && pkg.applicationInfo.primaryCpuAbi != null &&
+                !VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
+            final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
+            if (mInstaller.linkNativeLibraryDirectory(pkg.packageName, nativeLibPath, userId) < 0) {
+                Slog.w(TAG, "Failed linking native library dir");
+                return false;
+            }
+        }
+
         return true;
     }
 
@@ -12914,6 +12904,17 @@
                     Bundle extras) throws RemoteException {
                 Slog.d(TAG, "Install result for move: "
                         + PackageManager.installStatusToString(returnCode, msg));
+
+                // We usually have a new package now after the install, but if
+                // we failed we need to clear the pending flag on the original
+                // package object.
+                synchronized (mPackages) {
+                    final PackageParser.Package pkg = mPackages.get(packageName);
+                    if (pkg != null) {
+                        pkg.mOperationPending = false;
+                    }
+                }
+
                 final int status = PackageManager.installStatusToPublicStatus(returnCode);
                 switch (status) {
                     case PackageInstaller.STATUS_SUCCESS:
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ad87993..8ded7ca 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1576,6 +1576,7 @@
                     String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
                     String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
                     if (multiple != null) {
+                        values.clear();
                         int count = Integer.parseInt(multiple);
                         while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                             if (type == XmlPullParser.START_TAG
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f47a07c..5f97a00 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -821,7 +821,7 @@
                         + " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags));
             }
 
-            if ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0) {
+            if ((flags & PowerManager.WAIT_FOR_DISTANT_PROXIMITY) != 0) {
                 mRequestWaitForNegativeProximity = true;
             }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 27023ad..d22912c 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -33,6 +33,7 @@
 import android.content.IntentFilter;
 import android.content.OperationApplicationException;
 import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
@@ -49,9 +50,11 @@
 import android.media.tv.ITvInputSession;
 import android.media.tv.ITvInputSessionCallback;
 import android.media.tv.TvContentRating;
+import android.media.tv.TvContentRatingSystemInfo;
 import android.media.tv.TvContract;
 import android.media.tv.TvInputHardwareInfo;
 import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
 import android.media.tv.TvInputService;
 import android.media.tv.TvStreamConfig;
 import android.media.tv.TvTrackInfo;
@@ -116,7 +119,7 @@
 
         mContext = context;
         mContentResolver = context.getContentResolver();
-        mWatchLogHandler = new WatchLogHandler(IoThread.get().getLooper());
+        mWatchLogHandler = new WatchLogHandler(mContentResolver, IoThread.get().getLooper());
 
         mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener());
 
@@ -137,6 +140,7 @@
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 buildTvInputListLocked(mCurrentUserId);
+                buildTvContentRatingSystemListLocked(mCurrentUserId);
             }
         }
         mTvInputHardwareManager.onBootPhase(phase);
@@ -149,6 +153,7 @@
                 if (DEBUG) Slog.d(TAG, "onSomePackagesChanged()");
                 synchronized (mLock) {
                     buildTvInputListLocked(mCurrentUserId);
+                    buildTvContentRatingSystemListLocked(mCurrentUserId);
                 }
             }
 
@@ -243,7 +248,7 @@
                     serviceState = new ServiceState(component, userId);
                     userState.serviceStateMap.put(component, serviceState);
                 } else {
-                    inputList.addAll(serviceState.mInputList);
+                    inputList.addAll(serviceState.inputList);
                 }
             } else {
                 try {
@@ -253,9 +258,6 @@
                     continue;
                 }
             }
-
-            // Reconnect the service if existing input is updated.
-            updateServiceConnectionLocked(component, userId);
             userState.packageSet.add(si.packageName);
         }
 
@@ -268,7 +270,7 @@
             if (state == null) {
                 state = new TvInputState();
             }
-            state.mInfo = info;
+            state.info = info;
             inputMap.put(info.getId(), state);
         }
 
@@ -280,7 +282,7 @@
 
         for (String inputId : userState.inputMap.keySet()) {
             if (!inputMap.containsKey(inputId)) {
-                TvInputInfo info = userState.inputMap.get(inputId).mInfo;
+                TvInputInfo info = userState.inputMap.get(inputId).info;
                 ServiceState serviceState = userState.serviceStateMap.get(info.getComponent());
                 if (serviceState != null) {
                     abortPendingCreateSessionRequestsLocked(serviceState, inputId, userId);
@@ -291,15 +293,32 @@
 
         userState.inputMap.clear();
         userState.inputMap = inputMap;
+    }
 
-        userState.ratingSystemXmlUriSet.clear();
-        for (TvInputState state : userState.inputMap.values()) {
-            Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri();
-            if (ratingSystemXmlUri != null) {
-                // TODO: need to check the validation of xml format and the duplication of rating
-                // systems.
-                userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri());
+    private void buildTvContentRatingSystemListLocked(int userId) {
+        UserState userState = getUserStateLocked(userId);
+        userState.contentRatingSystemList.clear();
+
+        final PackageManager pm = mContext.getPackageManager();
+        Intent intent = new Intent(TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS);
+        for (ResolveInfo resolveInfo :
+                pm.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA)) {
+            ActivityInfo receiver = resolveInfo.activityInfo;
+            Bundle metaData = receiver.metaData;
+            if (metaData == null) {
+                continue;
             }
+
+            int xmlResId = metaData.getInt(TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS);
+            if (xmlResId == 0) {
+                Slog.w(TAG, "Missing meta-data '"
+                        + TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS + "' on receiver "
+                        + receiver.packageName + "/" + receiver.name);
+                continue;
+            }
+            userState.contentRatingSystemList.add(
+                    TvContentRatingSystemInfo.createTvContentRatingSystemInfo(xmlResId,
+                            receiver.applicationInfo));
         }
     }
 
@@ -318,6 +337,7 @@
             }
             mUserStates.put(userId, userState);
             buildTvInputListLocked(userId);
+            buildTvContentRatingSystemListLocked(userId);
         }
     }
 
@@ -329,9 +349,9 @@
             }
             // Release created sessions.
             for (SessionState state : userState.sessionStateMap.values()) {
-                if (state.mSession != null) {
+                if (state.session != null) {
                     try {
-                        state.mSession.release();
+                        state.session.release();
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in release", e);
                     }
@@ -341,21 +361,21 @@
 
             // Unregister all callbacks and unbind all services.
             for (ServiceState serviceState : userState.serviceStateMap.values()) {
-                if (serviceState.mCallback != null) {
+                if (serviceState.callback != null) {
                     try {
-                        serviceState.mService.unregisterCallback(serviceState.mCallback);
+                        serviceState.service.unregisterCallback(serviceState.callback);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in unregisterCallback", e);
                     }
                 }
-                mContext.unbindService(serviceState.mConnection);
+                mContext.unbindService(serviceState.connection);
             }
             userState.serviceStateMap.clear();
 
             // Clear everything else.
             userState.inputMap.clear();
             userState.packageSet.clear();
-            userState.ratingSystemXmlUriSet.clear();
+            userState.contentRatingSystemList.clear();
             userState.clientStateMap.clear();
             userState.callbackSet.clear();
             userState.mainSessionToken = null;
@@ -389,7 +409,7 @@
             throw new IllegalArgumentException("Session state not found for token " + sessionToken);
         }
         // Only the application that requested this session or the system can access it.
-        if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) {
+        if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.callingUid) {
             throw new SecurityException("Illegal access to the session with token " + sessionToken
                     + " from uid " + callingUid);
         }
@@ -401,10 +421,10 @@
     }
 
     private ITvInputSession getSessionLocked(SessionState sessionState) {
-        ITvInputSession session = sessionState.mSession;
+        ITvInputSession session = sessionState.session;
         if (session == null) {
             throw new IllegalStateException("Session not yet created for token "
-                    + sessionState.mSessionToken);
+                    + sessionState.sessionToken);
         }
         return session;
     }
@@ -416,8 +436,8 @@
     }
 
     private static boolean shouldMaintainConnection(ServiceState serviceState) {
-        return !serviceState.mSessionTokens.isEmpty() || serviceState.mIsHardware;
-        // TODO: Find a way to maintain connection only when necessary.
+        return !serviceState.sessionTokens.isEmpty() || serviceState.isHardware;
+        // TODO: Find a way to maintain connection to hardware TV input service only when necessary.
     }
 
     private void updateServiceConnectionLocked(ComponentName component, int userId) {
@@ -426,18 +446,18 @@
         if (serviceState == null) {
             return;
         }
-        if (serviceState.mReconnecting) {
-            if (!serviceState.mSessionTokens.isEmpty()) {
+        if (serviceState.reconnecting) {
+            if (!serviceState.sessionTokens.isEmpty()) {
                 // wait until all the sessions are removed.
                 return;
             }
-            serviceState.mReconnecting = false;
+            serviceState.reconnecting = false;
         }
         boolean maintainConnection = shouldMaintainConnection(serviceState);
-        if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) {
+        if (serviceState.service == null && maintainConnection && userId == mCurrentUserId) {
             // This means that the service is not yet connected but its state indicates that we
             // have pending requests. Then, connect the service.
-            if (serviceState.mBound) {
+            if (serviceState.bound) {
                 // We have already bound to the service so we don't try to bind again until after we
                 // unbind later on.
                 return;
@@ -447,18 +467,15 @@
             }
 
             Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component);
-            // Binding service may fail if the service is updating.
-            // In that case, the connection will be revived in buildTvInputListLocked called by
-            // onSomePackagesChanged.
-            serviceState.mBound = mContext.bindServiceAsUser(
-                    i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId));
-        } else if (serviceState.mService != null && !maintainConnection) {
+            serviceState.bound = mContext.bindServiceAsUser(
+                    i, serviceState.connection, Context.BIND_AUTO_CREATE, new UserHandle(userId));
+        } else if (serviceState.service != null && !maintainConnection) {
             // This means that the service is already connected but its state indicates that we have
             // nothing to do with it. Then, disconnect the service.
             if (DEBUG) {
                 Slog.d(TAG, "unbindService(service=" + component + ")");
             }
-            mContext.unbindService(serviceState.mConnection);
+            mContext.unbindService(serviceState.connection);
             userState.serviceStateMap.remove(component);
         }
     }
@@ -467,16 +484,20 @@
             String inputId, int userId) {
         // Let clients know the create session requests are failed.
         UserState userState = getUserStateLocked(userId);
-        for (IBinder sessionToken : serviceState.mSessionTokens) {
+        List<SessionState> sessionsToAbort = new ArrayList<>();
+        for (IBinder sessionToken : serviceState.sessionTokens) {
             SessionState sessionState = userState.sessionStateMap.get(sessionToken);
-            if (sessionState.mSession == null && (inputId == null
-                    || sessionState.mInfo.getId().equals(inputId))) {
-                removeSessionStateLocked(sessionToken, sessionState.mUserId);
-                sendSessionTokenToClientLocked(sessionState.mClient,
-                        sessionState.mInfo.getId(), null, null, sessionState.mSeq);
+            if (sessionState.session == null && (inputId == null
+                    || sessionState.info.getId().equals(inputId))) {
+                sessionsToAbort.add(sessionState);
             }
         }
-        updateServiceConnectionLocked(serviceState.mComponent, userId);
+        for (SessionState sessionState : sessionsToAbort) {
+            removeSessionStateLocked(sessionState.sessionToken, sessionState.userId);
+            sendSessionTokenToClientLocked(sessionState.client,
+                    sessionState.info.getId(), null, null, sessionState.seq);
+        }
+        updateServiceConnectionLocked(serviceState.component, userId);
     }
 
     private ClientState createClientStateLocked(IBinder clientToken, int userId) {
@@ -491,221 +512,26 @@
         return clientState;
     }
 
-    private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken,
-            final int userId) {
-        final UserState userState = getUserStateLocked(userId);
-        final SessionState sessionState = userState.sessionStateMap.get(sessionToken);
+    private void createSessionInternalLocked(ITvInputService service, IBinder sessionToken,
+            int userId) {
+        UserState userState = getUserStateLocked(userId);
+        SessionState sessionState = userState.sessionStateMap.get(sessionToken);
         if (DEBUG) {
-            Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")");
+            Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.info.getId() + ")");
         }
-
-        final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
+        InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
 
         // Set up a callback to send the session token.
-        ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() {
-            @Override
-            public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) {
-                if (DEBUG) {
-                    Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")");
-                }
-                synchronized (mLock) {
-                    sessionState.mSession = session;
-                    sessionState.mHardwareSessionToken = harewareSessionToken;
-                    if (session == null) {
-                        removeSessionStateLocked(sessionToken, userId);
-                        sendSessionTokenToClientLocked(sessionState.mClient,
-                                sessionState.mInfo.getId(), null, null, sessionState.mSeq);
-                    } else {
-                        try {
-                            session.asBinder().linkToDeath(sessionState, 0);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "session process has already died", e);
-                        }
-
-                        IBinder clientToken = sessionState.mClient.asBinder();
-                        ClientState clientState = userState.clientStateMap.get(clientToken);
-                        if (clientState == null) {
-                            clientState = createClientStateLocked(clientToken, userId);
-                        }
-                        clientState.mSessionTokens.add(sessionState.mSessionToken);
-
-                        sendSessionTokenToClientLocked(sessionState.mClient,
-                                sessionState.mInfo.getId(), sessionToken, channels[0],
-                                sessionState.mSeq);
-                    }
-                    channels[0].dispose();
-                }
-            }
-
-            @Override
-            public void onChannelRetuned(Uri channelUri) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onChannelRetuned(" + channelUri + ")");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        // TODO: Consider adding this channel change in the watch log. When we do
-                        // that, how we can protect the watch log from malicious tv inputs should
-                        // be addressed. e.g. add a field which represents where the channel change
-                        // originated from.
-                        sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onChannelRetuned", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onTracksChanged(List<TvTrackInfo> tracks) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onTracksChanged(" + tracks + ")");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onTracksChanged(tracks, sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onTracksChanged", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onTrackSelected(int type, String trackId) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onTrackSelected(type, trackId, sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onTrackSelected", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onVideoAvailable() {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onVideoAvailable()");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onVideoAvailable(sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onVideoAvailable", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onVideoUnavailable(int reason) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onVideoUnavailable(" + reason + ")");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onVideoUnavailable", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onContentAllowed() {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onContentAllowed()");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onContentAllowed(sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onContentAllowed", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onContentBlocked(String rating) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onContentBlocked()");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onContentBlocked(rating, sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onContentBlocked", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onLayoutSurface(int left, int top, int right, int bottom) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top
-                                + ", right=" + right + ", bottom=" + bottom + ",)");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onLayoutSurface(left, top, right, bottom,
-                                sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onLayoutSurface", e);
-                    }
-                }
-            }
-
-            @Override
-            public void onSessionEvent(String eventType, Bundle eventArgs) {
-                synchronized (mLock) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")");
-                    }
-                    if (sessionState.mSession == null || sessionState.mClient == null) {
-                        return;
-                    }
-                    try {
-                        sessionState.mClient.onSessionEvent(eventType, eventArgs,
-                                sessionState.mSeq);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in onSessionEvent", e);
-                    }
-                }
-            }
-        };
+        ITvInputSessionCallback callback = new SessionCallback(sessionState, channels);
 
         // Create a session. When failed, send a null token immediately.
         try {
-            service.createSession(channels[1], callback, sessionState.mInfo.getId());
+            service.createSession(channels[1], callback, sessionState.info.getId());
         } catch (RemoteException e) {
             Slog.e(TAG, "error in createSession", e);
             removeSessionStateLocked(sessionToken, userId);
-            sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null,
-                    null, sessionState.mSeq);
+            sendSessionTokenToClientLocked(sessionState.client, sessionState.info.getId(), null,
+                    null, sessionState.seq);
         }
         channels[1].dispose();
     }
@@ -721,17 +547,17 @@
 
     private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
-        if (sessionState.mSession != null) {
+        if (sessionState.session != null) {
             UserState userState = getUserStateLocked(userId);
             if (sessionToken == userState.mainSessionToken) {
                 setMainLocked(sessionToken, false, callingUid, userId);
             }
             try {
-                sessionState.mSession.release();
+                sessionState.session.release();
             } catch (RemoteException e) {
                 Slog.e(TAG, "session process has already died", e);
             }
-            sessionState.mSession = null;
+            sessionState.session = null;
         }
         removeSessionStateLocked(sessionToken, userId);
     }
@@ -754,26 +580,22 @@
 
         // Also remove the session token from the session token list of the current client and
         // service.
-        ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder());
+        ClientState clientState = userState.clientStateMap.get(sessionState.client.asBinder());
         if (clientState != null) {
-            clientState.mSessionTokens.remove(sessionToken);
+            clientState.sessionTokens.remove(sessionToken);
             if (clientState.isEmpty()) {
-                userState.clientStateMap.remove(sessionState.mClient.asBinder());
-                if (userState.clientStateMap.isEmpty()) {
-                    // No longer need to keep the callbacks since there is no client.
-                    userState.callbackSet.clear();
-                }
+                userState.clientStateMap.remove(sessionState.client.asBinder());
             }
         }
 
-        TvInputInfo info = sessionState.mInfo;
+        TvInputInfo info = sessionState.info;
         if (info != null) {
             ServiceState serviceState = userState.serviceStateMap.get(info.getComponent());
             if (serviceState != null) {
-                serviceState.mSessionTokens.remove(sessionToken);
+                serviceState.sessionTokens.remove(sessionToken);
             }
         }
-        updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId);
+        updateServiceConnectionLocked(sessionState.info.getComponent(), userId);
 
         // Log the end of watch.
         SomeArgs args = SomeArgs.obtain();
@@ -784,13 +606,12 @@
 
     private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) {
         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
-        if (sessionState.mHardwareSessionToken != null) {
-            sessionState = getSessionStateLocked(sessionState.mHardwareSessionToken,
+        if (sessionState.hardwareSessionToken != null) {
+            sessionState = getSessionStateLocked(sessionState.hardwareSessionToken,
                     Process.SYSTEM_UID, userId);
         }
-        ServiceState serviceState = getServiceStateLocked(sessionState.mInfo.getComponent(),
-                userId);
-        if (!serviceState.mIsHardware) {
+        ServiceState serviceState = getServiceStateLocked(sessionState.info.getComponent(), userId);
+        if (!serviceState.isHardware) {
             return;
         }
         ITvInputSession session = getSessionLocked(sessionState);
@@ -853,10 +674,10 @@
     private void setStateLocked(String inputId, int state, int userId) {
         UserState userState = getUserStateLocked(userId);
         TvInputState inputState = userState.inputMap.get(inputId);
-        ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent());
-        int oldState = inputState.mState;
-        inputState.mState = state;
-        if (serviceState != null && serviceState.mService == null
+        ServiceState serviceState = userState.serviceStateMap.get(inputState.info.getComponent());
+        int oldState = inputState.state;
+        inputState.state = state;
+        if (serviceState != null && serviceState.service == null
                 && shouldMaintainConnection(serviceState)) {
             // We don't notify state change while reconnecting. It should remain disconnected.
             return;
@@ -877,7 +698,7 @@
                     UserState userState = getUserStateLocked(resolvedUserId);
                     List<TvInputInfo> inputList = new ArrayList<TvInputInfo>();
                     for (TvInputState state : userState.inputMap.values()) {
-                        inputList.add(state.mInfo);
+                        inputList.add(state.info);
                     }
                     return inputList;
                 }
@@ -895,7 +716,7 @@
                 synchronized (mLock) {
                     UserState userState = getUserStateLocked(resolvedUserId);
                     TvInputState state = userState.inputMap.get(inputId);
-                    return state == null ? null : state.mInfo;
+                    return state == null ? null : state.info;
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -903,16 +724,14 @@
         }
 
         @Override
-        public List<Uri> getTvContentRatingSystemXmls(int userId) {
+        public List<TvContentRatingSystemInfo> getTvContentRatingSystemList(int userId) {
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
-                    Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls");
+                    Binder.getCallingUid(), userId, "getTvContentRatingSystemList");
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
                     UserState userState = getUserStateLocked(resolvedUserId);
-                    List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>();
-                    ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet);
-                    return ratingSystemXmlUriList;
+                    return userState.contentRatingSystemList;
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -943,8 +762,8 @@
                         Slog.e(TAG, "client process has already died", e);
                     }
                     for (TvInputState state : userState.inputMap.values()) {
-                        notifyInputStateChangedLocked(userState, state.mInfo.getId(),
-                                state.mState, callback);
+                        notifyInputStateChangedLocked(userState, state.info.getId(), state.state,
+                                callback);
                     }
                 }
             } finally {
@@ -1093,14 +912,14 @@
                         sendSessionTokenToClientLocked(client, inputId, null, null, seq);
                         return;
                     }
-                    TvInputInfo info = inputState.mInfo;
+                    TvInputInfo info = inputState.info;
                     ServiceState serviceState = userState.serviceStateMap.get(info.getComponent());
                     if (serviceState == null) {
                         serviceState = new ServiceState(info.getComponent(), resolvedUserId);
                         userState.serviceStateMap.put(info.getComponent(), serviceState);
                     }
                     // Send a null token immediately while reconnecting.
-                    if (serviceState.mReconnecting == true) {
+                    if (serviceState.reconnecting == true) {
                         sendSessionTokenToClientLocked(client, inputId, null, null, seq);
                         return;
                     }
@@ -1114,10 +933,10 @@
                     userState.sessionStateMap.put(sessionToken, sessionState);
 
                     // Also, add them to the session state map of the current service.
-                    serviceState.mSessionTokens.add(sessionToken);
+                    serviceState.sessionTokens.add(sessionToken);
 
-                    if (serviceState.mService != null) {
-                        createSessionInternalLocked(serviceState.mService, sessionToken,
+                    if (serviceState.service != null) {
+                        createSessionInternalLocked(serviceState.service, sessionToken,
                                 resolvedUserId);
                     } else {
                         updateServiceConnectionLocked(info.getComponent(), resolvedUserId);
@@ -1192,10 +1011,10 @@
                     try {
                         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
                                 resolvedUserId);
-                        if (sessionState.mHardwareSessionToken == null) {
+                        if (sessionState.hardwareSessionToken == null) {
                             getSessionLocked(sessionState).setSurface(surface);
                         } else {
-                            getSessionLocked(sessionState.mHardwareSessionToken,
+                            getSessionLocked(sessionState.hardwareSessionToken,
                                     Process.SYSTEM_UID, resolvedUserId).setSurface(surface);
                         }
                     } catch (RemoteException e) {
@@ -1223,9 +1042,10 @@
                     try {
                         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
                                 resolvedUserId);
-                        getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height);
-                        if (sessionState.mHardwareSessionToken != null) {
-                            getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID,
+                        getSessionLocked(sessionState).dispatchSurfaceChanged(format, width,
+                                height);
+                        if (sessionState.hardwareSessionToken != null) {
+                            getSessionLocked(sessionState.hardwareSessionToken, Process.SYSTEM_UID,
                                     resolvedUserId).dispatchSurfaceChanged(format, width, height);
                         }
                     } catch (RemoteException e) {
@@ -1251,10 +1071,10 @@
                         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
                                 resolvedUserId);
                         getSessionLocked(sessionState).setVolume(volume);
-                        if (sessionState.mHardwareSessionToken != null) {
+                        if (sessionState.hardwareSessionToken != null) {
                             // Here, we let the hardware session know only whether volume is on or
                             // off to prevent that the volume is controlled in the both side.
-                            getSessionLocked(sessionState.mHardwareSessionToken,
+                            getSessionLocked(sessionState.hardwareSessionToken,
                                     Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f)
                                             ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF);
                         }
@@ -1288,7 +1108,7 @@
 
                         // Log the start of watch.
                         SomeArgs args = SomeArgs.obtain();
-                        args.arg1 = sessionState.mInfo.getComponent().getPackageName();
+                        args.arg1 = sessionState.info.getComponent().getPackageName();
                         args.arg2 = System.currentTimeMillis();
                         args.arg3 = ContentUris.parseId(channelUri);
                         args.arg4 = params;
@@ -1548,10 +1368,10 @@
                         return false;
                     }
                     for (SessionState sessionState : userState.sessionStateMap.values()) {
-                        if (sessionState.mInfo.getId().equals(inputId)
-                                && sessionState.mHardwareSessionToken != null) {
+                        if (sessionState.info.getId().equals(inputId)
+                                && sessionState.hardwareSessionToken != null) {
                             hardwareInputId = userState.sessionStateMap.get(
-                                    sessionState.mHardwareSessionToken).mInfo.getId();
+                                    sessionState.hardwareSessionToken).info.getId();
                             break;
                         }
                     }
@@ -1580,8 +1400,8 @@
                         SessionState[] sessionStates = userState.sessionStateMap.values().toArray(
                                 new SessionState[0]);
                         // Check if there is a wrapper input.
-                        if (sessionStates[0].mHardwareSessionToken != null
-                                || sessionStates[1].mHardwareSessionToken != null) {
+                        if (sessionStates[0].hardwareSessionToken != null
+                                || sessionStates[1].hardwareSessionToken != null) {
                             return true;
                         }
                     }
@@ -1641,15 +1461,15 @@
 
                         pw.increaseIndent();
 
-                        pw.println("mSessionTokens:");
+                        pw.println("sessionTokens:");
                         pw.increaseIndent();
-                        for (IBinder token : client.mSessionTokens) {
+                        for (IBinder token : client.sessionTokens) {
                             pw.println("" + token);
                         }
                         pw.decreaseIndent();
 
-                        pw.println("mClientTokens: " + client.mClientToken);
-                        pw.println("mUserId: " + client.mUserId);
+                        pw.println("clientTokens: " + client.clientToken);
+                        pw.println("userId: " + client.userId);
 
                         pw.decreaseIndent();
                     }
@@ -1664,17 +1484,17 @@
 
                         pw.increaseIndent();
 
-                        pw.println("mSessionTokens:");
+                        pw.println("sessionTokens:");
                         pw.increaseIndent();
-                        for (IBinder token : service.mSessionTokens) {
+                        for (IBinder token : service.sessionTokens) {
                             pw.println("" + token);
                         }
                         pw.decreaseIndent();
 
-                        pw.println("mService: " + service.mService);
-                        pw.println("mCallback: " + service.mCallback);
-                        pw.println("mBound: " + service.mBound);
-                        pw.println("mReconnecting: " + service.mReconnecting);
+                        pw.println("service: " + service.service);
+                        pw.println("callback: " + service.callback);
+                        pw.println("bound: " + service.bound);
+                        pw.println("reconnecting: " + service.reconnecting);
 
                         pw.decreaseIndent();
                     }
@@ -1688,15 +1508,15 @@
                         pw.println(entry.getKey() + ": " + session);
 
                         pw.increaseIndent();
-                        pw.println("mInfo: " + session.mInfo);
-                        pw.println("mClient: " + session.mClient);
-                        pw.println("mSeq: " + session.mSeq);
-                        pw.println("mCallingUid: " + session.mCallingUid);
-                        pw.println("mUserId: " + session.mUserId);
-                        pw.println("mSessionToken: " + session.mSessionToken);
-                        pw.println("mSession: " + session.mSession);
-                        pw.println("mLogUri: " + session.mLogUri);
-                        pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken);
+                        pw.println("info: " + session.info);
+                        pw.println("client: " + session.client);
+                        pw.println("seq: " + session.seq);
+                        pw.println("callingUid: " + session.callingUid);
+                        pw.println("userId: " + session.userId);
+                        pw.println("sessionToken: " + session.sessionToken);
+                        pw.println("session: " + session.session);
+                        pw.println("logUri: " + session.logUri);
+                        pw.println("hardwareSessionToken: " + session.hardwareSessionToken);
                         pw.decreaseIndent();
                     }
                     pw.decreaseIndent();
@@ -1715,19 +1535,6 @@
         }
     }
 
-    private static final class TvInputState {
-        // A TvInputInfo object which represents the TV input.
-        private TvInputInfo mInfo;
-
-        // The state of TV input. Connected by default.
-        private int mState = INPUT_STATE_CONNECTED;
-
-        @Override
-        public String toString() {
-            return "mInfo: " + mInfo + "; mState: " + mState;
-        }
-    }
-
     private static final class UserState {
         // A mapping from the TV input id to its TvInputState.
         private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>();
@@ -1735,8 +1542,9 @@
         // A set of all TV input packages.
         private final Set<String> packageSet = new HashSet<String>();
 
-        // A set of all TV content rating system xml uris.
-        private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>();
+        // A list of all TV content rating systems defined.
+        private final List<TvContentRatingSystemInfo>
+                contentRatingSystemList = new ArrayList<TvContentRatingSystemInfo>();
 
         // A mapping from the token of a client to its state.
         private final Map<IBinder, ClientState> clientStateMap =
@@ -1767,104 +1575,117 @@
     }
 
     private final class ClientState implements IBinder.DeathRecipient {
-        private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
+        private final List<IBinder> sessionTokens = new ArrayList<IBinder>();
 
-        private IBinder mClientToken;
-        private final int mUserId;
+        private IBinder clientToken;
+        private final int userId;
 
         ClientState(IBinder clientToken, int userId) {
-            mClientToken = clientToken;
-            mUserId = userId;
+            this.clientToken = clientToken;
+            this.userId = userId;
         }
 
         public boolean isEmpty() {
-            return mSessionTokens.isEmpty();
+            return sessionTokens.isEmpty();
         }
 
         @Override
         public void binderDied() {
             synchronized (mLock) {
-                UserState userState = getUserStateLocked(mUserId);
+                UserState userState = getUserStateLocked(userId);
                 // DO NOT remove the client state of clientStateMap in this method. It will be
                 // removed in releaseSessionLocked().
-                ClientState clientState = userState.clientStateMap.get(mClientToken);
+                ClientState clientState = userState.clientStateMap.get(clientToken);
                 if (clientState != null) {
-                    while (clientState.mSessionTokens.size() > 0) {
+                    while (clientState.sessionTokens.size() > 0) {
                         releaseSessionLocked(
-                                clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId);
+                                clientState.sessionTokens.get(0), Process.SYSTEM_UID, userId);
                     }
                 }
-                mClientToken = null;
+                clientToken = null;
             }
         }
     }
 
     private final class ServiceState {
-        private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
-        private final ServiceConnection mConnection;
-        private final ComponentName mComponent;
-        private final boolean mIsHardware;
-        private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>();
+        private final List<IBinder> sessionTokens = new ArrayList<IBinder>();
+        private final ServiceConnection connection;
+        private final ComponentName component;
+        private final boolean isHardware;
+        private final List<TvInputInfo> inputList = new ArrayList<TvInputInfo>();
 
-        private ITvInputService mService;
-        private ServiceCallback mCallback;
-        private boolean mBound;
-        private boolean mReconnecting;
+        private ITvInputService service;
+        private ServiceCallback callback;
+        private boolean bound;
+        private boolean reconnecting;
 
         private ServiceState(ComponentName component, int userId) {
-            mComponent = component;
-            mConnection = new InputServiceConnection(component, userId);
-            mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mComponent);
+            this.component = component;
+            this.connection = new InputServiceConnection(component, userId);
+            this.isHardware = hasHardwarePermission(mContext.getPackageManager(), component);
+        }
+    }
+
+    private static final class TvInputState {
+        // A TvInputInfo object which represents the TV input.
+        private TvInputInfo info;
+
+        // The state of TV input. Connected by default.
+        private int state = INPUT_STATE_CONNECTED;
+
+        @Override
+        public String toString() {
+            return "info: " + info + "; state: " + state;
         }
     }
 
     private final class SessionState implements IBinder.DeathRecipient {
-        private final TvInputInfo mInfo;
-        private final ITvInputClient mClient;
-        private final int mSeq;
-        private final int mCallingUid;
-        private final int mUserId;
-        private final IBinder mSessionToken;
-        private ITvInputSession mSession;
-        private Uri mLogUri;
+        private final TvInputInfo info;
+        private final ITvInputClient client;
+        private final int seq;
+        private final int callingUid;
+        private final int userId;
+        private final IBinder sessionToken;
+        private ITvInputSession session;
+        private Uri logUri;
         // Not null if this session represents an external device connected to a hardware TV input.
-        private IBinder mHardwareSessionToken;
+        private IBinder hardwareSessionToken;
 
         private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client,
                 int seq, int callingUid, int userId) {
-            mSessionToken = sessionToken;
-            mInfo = info;
-            mClient = client;
-            mSeq = seq;
-            mCallingUid = callingUid;
-            mUserId = userId;
+            this.sessionToken = sessionToken;
+            this.info = info;
+            this.client = client;
+            this.seq = seq;
+            this.callingUid = callingUid;
+            this.userId = userId;
         }
 
         @Override
         public void binderDied() {
             synchronized (mLock) {
-                mSession = null;
-                if (mClient != null) {
+                session = null;
+                if (client != null) {
                     try {
-                        mClient.onSessionReleased(mSeq);
+                        client.onSessionReleased(seq);
                     } catch(RemoteException e) {
                         Slog.e(TAG, "error in onSessionReleased", e);
                     }
                 }
                 // If there are any other sessions based on this session, they should be released.
-                UserState userState = getUserStateLocked(mUserId);
+                UserState userState = getUserStateLocked(userId);
                 for (SessionState sessionState : userState.sessionStateMap.values()) {
-                    if (mSessionToken == sessionState.mHardwareSessionToken) {
-                        releaseSessionLocked(sessionState.mSessionToken, Process.SYSTEM_UID,
-                                mUserId);
+                    if (sessionToken == sessionState.hardwareSessionToken) {
+                        releaseSessionLocked(sessionState.sessionToken, Process.SYSTEM_UID,
+                                userId);
                         try {
-                            sessionState.mClient.onSessionReleased(sessionState.mSeq);
+                            sessionState.client.onSessionReleased(sessionState.seq);
                         } catch (RemoteException e) {
                             Slog.e(TAG, "error in onSessionReleased", e);
                         }
                     }
                 }
-                removeSessionStateLocked(mSessionToken, mUserId);
+                removeSessionStateLocked(sessionToken, userId);
             }
         }
     }
@@ -1886,37 +1707,37 @@
             synchronized (mLock) {
                 UserState userState = getUserStateLocked(mUserId);
                 ServiceState serviceState = userState.serviceStateMap.get(mComponent);
-                serviceState.mService = ITvInputService.Stub.asInterface(service);
+                serviceState.service = ITvInputService.Stub.asInterface(service);
 
                 // Register a callback, if we need to.
-                if (serviceState.mIsHardware && serviceState.mCallback == null) {
-                    serviceState.mCallback = new ServiceCallback(mComponent, mUserId);
+                if (serviceState.isHardware && serviceState.callback == null) {
+                    serviceState.callback = new ServiceCallback(mComponent, mUserId);
                     try {
-                        serviceState.mService.registerCallback(serviceState.mCallback);
+                        serviceState.service.registerCallback(serviceState.callback);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in registerCallback", e);
                     }
                 }
 
                 // And create sessions, if any.
-                for (IBinder sessionToken : serviceState.mSessionTokens) {
-                    createSessionInternalLocked(serviceState.mService, sessionToken, mUserId);
+                for (IBinder sessionToken : serviceState.sessionTokens) {
+                    createSessionInternalLocked(serviceState.service, sessionToken, mUserId);
                 }
 
                 for (TvInputState inputState : userState.inputMap.values()) {
-                    if (inputState.mInfo.getComponent().equals(component)
-                            && inputState.mState != INPUT_STATE_DISCONNECTED) {
-                        notifyInputStateChangedLocked(userState, inputState.mInfo.getId(),
-                                inputState.mState, null);
+                    if (inputState.info.getComponent().equals(component)
+                            && inputState.state != INPUT_STATE_DISCONNECTED) {
+                        notifyInputStateChangedLocked(userState, inputState.info.getId(),
+                                inputState.state, null);
                     }
                 }
 
-                if (serviceState.mIsHardware) {
+                if (serviceState.isHardware) {
                     List<TvInputHardwareInfo> hardwareInfoList =
                             mTvInputHardwareManager.getHardwareList();
                     for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) {
                         try {
-                            serviceState.mService.notifyHardwareAdded(hardwareInfo);
+                            serviceState.service.notifyHardwareAdded(hardwareInfo);
                         } catch (RemoteException e) {
                             Slog.e(TAG, "error in notifyHardwareAdded", e);
                         }
@@ -1926,7 +1747,7 @@
                             mTvInputHardwareManager.getHdmiDeviceList();
                     for (HdmiDeviceInfo deviceInfo : deviceInfoList) {
                         try {
-                            serviceState.mService.notifyHdmiDeviceAdded(deviceInfo);
+                            serviceState.service.notifyHdmiDeviceAdded(deviceInfo);
                         } catch (RemoteException e) {
                             Slog.e(TAG, "error in notifyHdmiDeviceAdded", e);
                         }
@@ -1948,16 +1769,16 @@
                 UserState userState = getUserStateLocked(mUserId);
                 ServiceState serviceState = userState.serviceStateMap.get(mComponent);
                 if (serviceState != null) {
-                    serviceState.mReconnecting = true;
-                    serviceState.mBound = false;
-                    serviceState.mService = null;
-                    serviceState.mCallback = null;
+                    serviceState.reconnecting = true;
+                    serviceState.bound = false;
+                    serviceState.service = null;
+                    serviceState.callback = null;
 
                     abortPendingCreateSessionRequestsLocked(serviceState, null, mUserId);
 
                     for (TvInputState inputState : userState.inputMap.values()) {
-                        if (inputState.mInfo.getComponent().equals(component)) {
-                            notifyInputStateChangedLocked(userState, inputState.mInfo.getId(),
+                        if (inputState.info.getComponent().equals(component)) {
+                            notifyInputStateChangedLocked(userState, inputState.info.getId(),
                                     INPUT_STATE_DISCONNECTED, null);
                         }
                     }
@@ -1990,7 +1811,7 @@
 
         private void addTvInputLocked(TvInputInfo inputInfo) {
             ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
-            serviceState.mInputList.add(inputInfo);
+            serviceState.inputList.add(inputInfo);
             buildTvInputListLocked(mUserId);
         }
 
@@ -2020,7 +1841,7 @@
             synchronized (mLock) {
                 ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
                 boolean removed = false;
-                for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator();
+                for (Iterator<TvInputInfo> it = serviceState.inputList.iterator();
                         it.hasNext(); ) {
                     if (it.next().getId().equals(inputId)) {
                         it.remove();
@@ -2038,7 +1859,211 @@
         }
     }
 
-    private final class WatchLogHandler extends Handler {
+    private final class SessionCallback extends ITvInputSessionCallback.Stub {
+        private final SessionState sessionState;
+        private final InputChannel[] mChannels;
+
+        SessionCallback(SessionState sessionState, InputChannel[] channels) {
+            this.sessionState = sessionState;
+            mChannels = channels;
+        }
+
+        @Override
+        public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) {
+            if (DEBUG) {
+                Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.info.getId() + ")");
+            }
+            synchronized (mLock) {
+                sessionState.session = session;
+                sessionState.hardwareSessionToken = harewareSessionToken;
+                if (session == null) {
+                    removeSessionStateLocked(sessionState.sessionToken, sessionState.userId);
+                    sendSessionTokenToClientLocked(sessionState.client,
+                            sessionState.info.getId(), null, null, sessionState.seq);
+                } else {
+                    try {
+                        session.asBinder().linkToDeath(sessionState, 0);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "session process has already died", e);
+                    }
+
+                    IBinder clientToken = sessionState.client.asBinder();
+                    UserState userState = getUserStateLocked(sessionState.userId);
+                    ClientState clientState = userState.clientStateMap.get(clientToken);
+                    if (clientState == null) {
+                        clientState = createClientStateLocked(clientToken, sessionState.userId);
+                    }
+                    clientState.sessionTokens.add(sessionState.sessionToken);
+
+                    sendSessionTokenToClientLocked(sessionState.client,
+                            sessionState.info.getId(), sessionState.sessionToken, mChannels[0],
+                            sessionState.seq);
+                }
+                mChannels[0].dispose();
+            }
+        }
+
+        @Override
+        public void onChannelRetuned(Uri channelUri) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onChannelRetuned(" + channelUri + ")");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    // TODO: Consider adding this channel change in the watch log. When we do
+                    // that, how we can protect the watch log from malicious tv inputs should
+                    // be addressed. e.g. add a field which represents where the channel change
+                    // originated from.
+                    sessionState.client.onChannelRetuned(channelUri, sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onChannelRetuned", e);
+                }
+            }
+        }
+
+        @Override
+        public void onTracksChanged(List<TvTrackInfo> tracks) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onTracksChanged(" + tracks + ")");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onTracksChanged(tracks, sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onTracksChanged", e);
+                }
+            }
+        }
+
+        @Override
+        public void onTrackSelected(int type, String trackId) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onTrackSelected(type, trackId, sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onTrackSelected", e);
+                }
+            }
+        }
+
+        @Override
+        public void onVideoAvailable() {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onVideoAvailable()");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onVideoAvailable(sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onVideoAvailable", e);
+                }
+            }
+        }
+
+        @Override
+        public void onVideoUnavailable(int reason) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onVideoUnavailable(" + reason + ")");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onVideoUnavailable(reason, sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onVideoUnavailable", e);
+                }
+            }
+        }
+
+        @Override
+        public void onContentAllowed() {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onContentAllowed()");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onContentAllowed(sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onContentAllowed", e);
+                }
+            }
+        }
+
+        @Override
+        public void onContentBlocked(String rating) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onContentBlocked()");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onContentBlocked(rating, sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onContentBlocked", e);
+                }
+            }
+        }
+
+        @Override
+        public void onLayoutSurface(int left, int top, int right, int bottom) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top
+                            + ", right=" + right + ", bottom=" + bottom + ",)");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onLayoutSurface(left, top, right, bottom, sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onLayoutSurface", e);
+                }
+            }
+        }
+
+        @Override
+        public void onSessionEvent(String eventType, Bundle eventArgs) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")");
+                }
+                if (sessionState.session == null || sessionState.client == null) {
+                    return;
+                }
+                try {
+                    sessionState.client.onSessionEvent(eventType, eventArgs,
+                            sessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onSessionEvent", e);
+                }
+            }
+        }
+    }
+
+    private static final class WatchLogHandler extends Handler {
         // There are only two kinds of watch events that can happen on the system:
         // 1. The current TV input session is tuned to a new channel.
         // 2. The session is released for some reason.
@@ -2050,8 +2075,11 @@
         private static final int MSG_LOG_WATCH_START = 1;
         private static final int MSG_LOG_WATCH_END = 2;
 
-        public WatchLogHandler(Looper looper) {
+        private final ContentResolver mContentResolver;
+
+        public WatchLogHandler(ContentResolver contentResolver, Looper looper) {
             super(looper);
+            mContentResolver = contentResolver;
         }
 
         @Override
@@ -2137,7 +2165,7 @@
         }
     }
 
-    final class HardwareListener implements TvInputHardwareManager.Listener {
+    private final class HardwareListener implements TvInputHardwareManager.Listener {
         @Override
         public void onStateChanged(String inputId, int state) {
             synchronized (mLock) {
@@ -2151,9 +2179,9 @@
                 UserState userState = getUserStateLocked(mCurrentUserId);
                 // Broadcast the event to all hardware inputs.
                 for (ServiceState serviceState : userState.serviceStateMap.values()) {
-                    if (!serviceState.mIsHardware || serviceState.mService == null) continue;
+                    if (!serviceState.isHardware || serviceState.service == null) continue;
                     try {
-                        serviceState.mService.notifyHardwareAdded(info);
+                        serviceState.service.notifyHardwareAdded(info);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in notifyHardwareAdded", e);
                     }
@@ -2167,9 +2195,9 @@
                 UserState userState = getUserStateLocked(mCurrentUserId);
                 // Broadcast the event to all hardware inputs.
                 for (ServiceState serviceState : userState.serviceStateMap.values()) {
-                    if (!serviceState.mIsHardware || serviceState.mService == null) continue;
+                    if (!serviceState.isHardware || serviceState.service == null) continue;
                     try {
-                        serviceState.mService.notifyHardwareRemoved(info);
+                        serviceState.service.notifyHardwareRemoved(info);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in notifyHardwareRemoved", e);
                     }
@@ -2183,9 +2211,9 @@
                 UserState userState = getUserStateLocked(mCurrentUserId);
                 // Broadcast the event to all hardware inputs.
                 for (ServiceState serviceState : userState.serviceStateMap.values()) {
-                    if (!serviceState.mIsHardware || serviceState.mService == null) continue;
+                    if (!serviceState.isHardware || serviceState.service == null) continue;
                     try {
-                        serviceState.mService.notifyHdmiDeviceAdded(deviceInfo);
+                        serviceState.service.notifyHdmiDeviceAdded(deviceInfo);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in notifyHdmiDeviceAdded", e);
                     }
@@ -2199,9 +2227,9 @@
                 UserState userState = getUserStateLocked(mCurrentUserId);
                 // Broadcast the event to all hardware inputs.
                 for (ServiceState serviceState : userState.serviceStateMap.values()) {
-                    if (!serviceState.mIsHardware || serviceState.mService == null) continue;
+                    if (!serviceState.isHardware || serviceState.service == null) continue;
                     try {
-                        serviceState.mService.notifyHdmiDeviceRemoved(deviceInfo);
+                        serviceState.service.notifyHdmiDeviceRemoved(deviceInfo);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e);
                     }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 09c4e20..9ceac41 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -41,11 +41,11 @@
 
     void addAppToken(int addPos, AppWindowToken wtoken) {
         final int lastPos = mAppTokens.size();
-        if (addPos > lastPos) {
-            // We lost an app token. Don't crash though.
-            Slog.e(TAG, "Task.addAppToken: Out of bounds attempt token=" + wtoken + " addPos="
-                    + addPos + " lastPos=" + lastPos);
-            addPos = lastPos;
+        for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
+            if (mAppTokens.get(pos).removed) {
+                // addPos assumes removed tokens are actually gone.
+                ++addPos;
+            }
         }
         mAppTokens.add(addPos, wtoken);
         mDeferRemoval = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e144bde..c70cb22 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2382,7 +2382,6 @@
             origId = Binder.clearCallingIdentity();
 
             if (addToken) {
-                Slog.w("BadTokenDebug", "addWindow: Adding token=" + token + " attrs.token=" + attrs.token);
                 mTokenMap.put(attrs.token, token);
             }
             win.attach();
@@ -2664,9 +2663,7 @@
                 + token.windows.size());
         if (token.windows.size() == 0) {
             if (!token.explicit) {
-                WindowToken wtoken = mTokenMap.remove(token.token);
-                Slog.w("BadTokenDebug", "removeWindowInnerLocked: Removing token=" + token + " removed=" +
-                        wtoken + " Callers=" + Debug.getCallers(4));
+                mTokenMap.remove(token.token);
             } else if (atoken != null) {
                 atoken.firstWindowDrawn = false;
             }
@@ -3452,7 +3449,6 @@
                 return;
             }
             wtoken = new WindowToken(this, token, type, true);
-            Slog.w("BadTokenDebug", "addWindowToken: Adding token=" + token + " wtoken=" + wtoken);
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
@@ -3471,8 +3467,6 @@
         synchronized(mWindowMap) {
             DisplayContent displayContent = null;
             WindowToken wtoken = mTokenMap.remove(token);
-            Slog.w("BadTokenDebug", "removeWindowToken: Removing token=" + token + " removed=" + wtoken
-                    + " Callers=" + Debug.getCallers(3));
             if (wtoken != null) {
                 boolean delayed = false;
                 if (!wtoken.hidden) {
@@ -3589,7 +3583,6 @@
                 task.addAppToken(addPos, atoken);
             }
 
-            Slog.w("BadTokenDebug", "addAppToken: Adding token=" + token.asBinder() + " atoken=" + atoken);
             mTokenMap.put(token.asBinder(), atoken);
 
             // Application tokens start out hidden.
@@ -4689,7 +4682,6 @@
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
             WindowToken basewtoken = mTokenMap.remove(token);
-            Slog.w("BadTokenDebug", "removeAppToke: Removing token=" + token + " removed=" + basewtoken);
             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
                 delayed = setTokenVisibilityLocked(wtoken, null, false,
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 38433ae..4b7dd08 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -754,7 +754,11 @@
                 final boolean isHwAccelerated = (attrs.flags &
                         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
                 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
-                if (!PixelFormat.formatHasAlpha(attrs.format)) {
+                if (!PixelFormat.formatHasAlpha(attrs.format)
+                        && attrs.surfaceInsets.left == 0
+                        && attrs.surfaceInsets.top == 0
+                        && attrs.surfaceInsets.right == 0
+                        && attrs.surfaceInsets.bottom  == 0) {
                     flags |= SurfaceControl.OPAQUE;
                 }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7baa258..564a3df 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -167,6 +167,27 @@
         DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
     }
 
+    private static final Set<String> SECURE_SETTINGS_WHITELIST;
+    private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
+    static {
+        SECURE_SETTINGS_WHITELIST = new HashSet();
+        SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
+        SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
+
+        GLOBAL_SETTINGS_WHITELIST = new HashSet();
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME_ZONE);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.BLUETOOTH_ON);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DATA_ROAMING);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.MODE_RINGER);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.NETWORK_PREFERENCE);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_ON);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_SLEEP_POLICY);
+    }
+
     final Context mContext;
     final UserManager mUserManager;
     final PowerManager.WakeLock mWakeLock;
@@ -287,6 +308,7 @@
         private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
         private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
         private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
+        private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
         private static final String TAG_ACCOUNT_TYPE = "account-type";
         private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
                 = "permitted-accessiblity-services";
@@ -365,6 +387,7 @@
         boolean disableCamera = false;
         boolean disableCallerId = false;
         boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
+        boolean requireAutoTime = false; // Can only be set by a device owner.
 
         Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
 
@@ -501,6 +524,11 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(disableScreenCapture));
                 out.endTag(null, TAG_DISABLE_SCREEN_CAPTURE);
             }
+            if (requireAutoTime) {
+                out.startTag(null, TAG_REQUIRE_AUTO_TIME);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(requireAutoTime));
+                out.endTag(null, TAG_REQUIRE_AUTO_TIME);
+            }
             if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
                 out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
                 out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
@@ -634,6 +662,9 @@
                 } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
                     disableScreenCapture = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
+                    requireAutoTime= Boolean.parseBoolean(
+                            parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
                     disabledKeyguardFeatures = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
@@ -818,6 +849,8 @@
                     pw.println(disableCallerId);
             pw.print(prefix); pw.print("disableScreenCapture=");
                     pw.println(disableScreenCapture);
+            pw.print(prefix); pw.print("requireAutoTime=");
+                    pw.println(requireAutoTime);
             pw.print(prefix); pw.print("disabledKeyguardFeatures=");
                     pw.println(disabledKeyguardFeatures);
             pw.print(prefix); pw.print("crossProfileWidgetProviders=");
@@ -3291,6 +3324,7 @@
         if (!mHasFeature) {
             return;
         }
+        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3343,6 +3377,51 @@
     }
 
     /**
+     * Set whether auto time is required by the specified admin (must be device owner).
+     */
+    public void setAutoTimeRequired(ComponentName who, int userHandle, boolean required) {
+        if (!mHasFeature) {
+            return;
+        }
+        enforceCrossUserPermission(userHandle);
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            if (admin.requireAutoTime != required) {
+                admin.requireAutoTime = required;
+                saveSettingsLocked(userHandle);
+            }
+        }
+
+        // Turn AUTO_TIME on in settings if it is required
+        if (required) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                Settings.Global.putInt(mContext.getContentResolver(),
+                        Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    /**
+     * Returns whether or not auto time is required by the device owner.
+     */
+    public boolean getAutoTimeRequired() {
+        if (!mHasFeature) {
+            return false;
+        }
+        synchronized (this) {
+            ActiveAdmin deviceOwner = getDeviceOwnerAdmin();
+            return (deviceOwner != null) ? deviceOwner.requireAutoTime : false;
+        }
+    }
+
+    /**
      * The system property used to share the state of the camera. The native camera service
      * is expected to read this property and act accordingly.
      */
@@ -3522,6 +3601,24 @@
         return null;
     }
 
+    // Returns the active device owner or null if there is no device owner.
+    private ActiveAdmin getDeviceOwnerAdmin() {
+        String deviceOwnerPackageName = getDeviceOwner();
+        if (deviceOwnerPackageName == null) {
+            return null;
+        }
+
+        DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+        final int n = policy.mAdminList.size();
+        for (int i = 0; i < n; i++) {
+            ActiveAdmin admin = policy.mAdminList.get(i);
+            if (deviceOwnerPackageName.equals(admin.info.getPackageName())) {
+                return admin;
+            }
+        }
+        return null;
+    }
+
     @Override
     public void clearDeviceOwner(String packageName) {
         if (packageName == null) {
@@ -3643,6 +3740,7 @@
         if (!mHasFeature) {
             return;
         }
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             // Check for permissions
             if (who == null) {
@@ -3656,7 +3754,7 @@
             try {
                 mUserManager.setUserEnabled(userId);
                 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
-                intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
+                intent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
                         Intent.FLAG_RECEIVER_FOREGROUND);
                 // TODO This should send to parent of profile (which is always owner at the moment).
@@ -3843,6 +3941,8 @@
     @Override
     public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
             ComponentName activity) {
+        final int userHandle = UserHandle.getCallingUserId();
+
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3852,7 +3952,7 @@
             IPackageManager pm = AppGlobals.getPackageManager();
             long id = Binder.clearCallingIdentity();
             try {
-                pm.addPersistentPreferredActivity(filter, activity, UserHandle.getCallingUserId());
+                pm.addPersistentPreferredActivity(filter, activity, userHandle);
             } catch (RemoteException re) {
                 // Shouldn't happen
             } finally {
@@ -3863,6 +3963,8 @@
 
     @Override
     public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
+        final int userHandle = UserHandle.getCallingUserId();
+
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3872,7 +3974,7 @@
             IPackageManager pm = AppGlobals.getPackageManager();
             long id = Binder.clearCallingIdentity();
             try {
-                pm.clearPackagePersistentPreferredActivities(packageName, UserHandle.getCallingUserId());
+                pm.clearPackagePersistentPreferredActivities(packageName, userHandle);
             } catch (RemoteException re) {
                 // Shouldn't happen
             } finally {
@@ -4498,7 +4600,6 @@
     @Override
     public void setUserRestriction(ComponentName who, String key, boolean enabled) {
         final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
-
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -4509,13 +4610,28 @@
             if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
                 throw new SecurityException("Profile owners cannot set user restriction " + key);
             }
+            boolean alreadyRestricted = mUserManager.hasUserRestriction(key, userHandle);
 
+            IAudioService iAudioService = null;
+            if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)
+                    || UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
+                iAudioService = IAudioService.Stub.asInterface(
+                        ServiceManager.getService(Context.AUDIO_SERVICE));
+            }
+
+            if (enabled && !alreadyRestricted) {
+                try {
+                    if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
+                        iAudioService.setMicrophoneMute(true, who.getPackageName());
+                    } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
+                        iAudioService.setMasterMute(true, 0, who.getPackageName(), null);
+                    }
+                } catch (RemoteException re) {
+                    Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
+                }
+            }
             long id = Binder.clearCallingIdentity();
             try {
-                AudioManager audioManager =
-                        (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-                boolean alreadyRestricted = mUserManager.hasUserRestriction(key);
-
                 if (enabled && !alreadyRestricted) {
                     if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
                         Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -4546,26 +4662,23 @@
                         Settings.Secure.putIntForUser(mContext.getContentResolver(),
                                 Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
                                 userHandle.getIdentifier());
-                    } else if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
-                        audioManager.setMicrophoneMute(true);
-                    } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        audioManager.setMasterMute(true);
                     }
                 }
-
                 mUserManager.setUserRestriction(key, enabled, userHandle);
-
-                if (!enabled && alreadyRestricted) {
-                    if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
-                        audioManager.setMicrophoneMute(false);
-                    } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        audioManager.setMasterMute(false);
-                    }
-                }
-
             } finally {
                 restoreCallingIdentity(id);
             }
+            if (!enabled && alreadyRestricted) {
+                try {
+                    if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
+                        iAudioService.setMicrophoneMute(false, who.getPackageName());
+                    } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
+                        iAudioService.setMasterMute(false, 0, who.getPackageName(), null);
+                    }
+                } catch (RemoteException re) {
+                    Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
+                }
+            }
         }
     }
 
@@ -4793,7 +4906,7 @@
     }
 
     @Override
-    public boolean getUninstallBlocked(ComponentName who, String packageName) {
+    public boolean isUninstallBlocked(ComponentName who, String packageName) {
         final int userId = UserHandle.getCallingUserId();
 
         synchronized (this) {
@@ -4964,6 +5077,11 @@
             }
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
 
+            if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)) {
+                throw new SecurityException(String.format(
+                        "Permission denial: device owners cannot update %1$s", setting));
+            }
+
             long id = Binder.clearCallingIdentity();
             try {
                 Settings.Global.putString(contentResolver, setting, value);
@@ -4984,6 +5102,11 @@
             }
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
+            if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
+                throw new SecurityException(String.format(
+                        "Permission denial: profile/device owners cannot update %1$s", setting));
+            }
+
             long id = Binder.clearCallingIdentity();
             try {
                 Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0f2aabc..f339dba 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -918,7 +918,7 @@
                 mSystemServiceManager.startService(HdmiControlService.class);
             }
 
-            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)) {
                 mSystemServiceManager.startService(TvInputManagerService.class);
             }
 
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index a71f739..7c596c1 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -89,6 +89,7 @@
         private final int mCallerDisplayNamePresentation;
         private final PhoneAccountHandle mAccountHandle;
         private final int mCallCapabilities;
+        private final int mCallProperties;
         private final int mDisconnectCauseCode;
         private final String mDisconnectCauseMessage;
         private final long mConnectTimeMillis;
@@ -145,6 +146,14 @@
         }
 
         /**
+         * @return A bitmask of the properties of the {@code Call}, as defined in
+         *         {@link CallProperties}.
+         */
+        public int getCallProperties() {
+            return mCallProperties;
+        }
+
+        /**
          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
          * as a code chosen from among those declared in {@link DisconnectCause}.
          */
@@ -210,6 +219,7 @@
                                 d.mCallerDisplayNamePresentation) &&
                         Objects.equals(mAccountHandle, d.mAccountHandle) &&
                         Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
+                        Objects.equals(mCallProperties, d.mCallProperties) &&
                         Objects.equals(mDisconnectCauseCode, d.mDisconnectCauseCode) &&
                         Objects.equals(mDisconnectCauseMessage, d.mDisconnectCauseMessage) &&
                         Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
@@ -230,6 +240,7 @@
                     Objects.hashCode(mCallerDisplayNamePresentation) +
                     Objects.hashCode(mAccountHandle) +
                     Objects.hashCode(mCallCapabilities) +
+                    Objects.hashCode(mCallProperties) +
                     Objects.hashCode(mDisconnectCauseCode) +
                     Objects.hashCode(mDisconnectCauseMessage) +
                     Objects.hashCode(mConnectTimeMillis) +
@@ -247,6 +258,7 @@
                 int callerDisplayNamePresentation,
                 PhoneAccountHandle accountHandle,
                 int capabilities,
+                int properties,
                 int disconnectCauseCode,
                 String disconnectCauseMessage,
                 long connectTimeMillis,
@@ -260,6 +272,7 @@
             mCallerDisplayNamePresentation = callerDisplayNamePresentation;
             mAccountHandle = accountHandle;
             mCallCapabilities = capabilities;
+            mCallProperties = properties;
             mDisconnectCauseCode = disconnectCauseCode;
             mDisconnectCauseMessage = disconnectCauseMessage;
             mConnectTimeMillis = connectTimeMillis;
@@ -642,6 +655,7 @@
                 parcelableCall.getCallerDisplayNamePresentation(),
                 parcelableCall.getAccountHandle(),
                 parcelableCall.getCapabilities(),
+                parcelableCall.getProperties(),
                 parcelableCall.getDisconnectCauseCode(),
                 parcelableCall.getDisconnectCauseMsg(),
                 parcelableCall.getConnectTimeMillis(),
@@ -743,6 +757,16 @@
         fireStartActivity(intent);
     }
 
+    /** {@hide} */
+    final void internalSetDisconnected() {
+        if (mState != Call.STATE_DISCONNECTED) {
+            mState = Call.STATE_DISCONNECTED;
+            fireStateChanged(mState);
+            fireCallDestroyed();
+            mPhone.internalRemoveCall(this);
+        }
+    }
+
     private void fireStateChanged(int newState) {
         for (Listener listener : mListeners) {
             listener.onStateChanged(this, newState);
diff --git a/telecomm/java/android/telecomm/CallProperties.java b/telecomm/java/android/telecomm/CallProperties.java
new file mode 100644
index 0000000..90eb0cb
--- /dev/null
+++ b/telecomm/java/android/telecomm/CallProperties.java
@@ -0,0 +1,26 @@
+/*
+ * 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.telecomm;
+
+/**
+ * Defines properties of a phone call which may be affected by changes to the call.
+ * @hide
+ */
+public class CallProperties {
+    /** Call is currently in a conference call. */
+    public static final int CONFERENCE                      = 0x00000001;
+}
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index a062632..cbcee75 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -163,6 +163,16 @@
         return new InCallServiceBinder();
     }
 
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Phone oldPhone = mPhone;
+        mPhone = null;
+
+        oldPhone.destroy();
+        onPhoneDestroyed(oldPhone);
+        return false;
+    }
+
     /**
      * Obtain the {@code Phone} associated with this {@code InCallService}.
      *
diff --git a/telecomm/java/android/telecomm/ParcelableCall.java b/telecomm/java/android/telecomm/ParcelableCall.java
index 8098b94..a2aa192 100644
--- a/telecomm/java/android/telecomm/ParcelableCall.java
+++ b/telecomm/java/android/telecomm/ParcelableCall.java
@@ -40,6 +40,7 @@
     private final String mDisconnectCauseMsg;
     private final List<String> mCannedSmsResponses;
     private final int mCapabilities;
+    private final int mProperties;
     private final long mConnectTimeMillis;
     private final Uri mHandle;
     private final int mHandlePresentation;
@@ -63,6 +64,7 @@
             String disconnectCauseMsg,
             List<String> cannedSmsResponses,
             int capabilities,
+            int properties,
             long connectTimeMillis,
             Uri handle,
             int handlePresentation,
@@ -83,6 +85,7 @@
         mDisconnectCauseMsg = disconnectCauseMsg;
         mCannedSmsResponses = cannedSmsResponses;
         mCapabilities = capabilities;
+        mProperties = properties;
         mConnectTimeMillis = connectTimeMillis;
         mHandle = handle;
         mHandlePresentation = handlePresentation;
@@ -137,6 +140,9 @@
         return mCapabilities;
     }
 
+    /** Bitmask of properties of the call. */
+    public int getProperties() { return mProperties; }
+
     /** The time that the call switched to the active state. */
     public long getConnectTimeMillis() {
         return mConnectTimeMillis;
@@ -246,6 +252,7 @@
             List<String> cannedSmsResponses = new ArrayList<>();
             source.readList(cannedSmsResponses, classLoader);
             int capabilities = source.readInt();
+            int properties = source.readInt();
             long connectTimeMillis = source.readLong();
             Uri handle = source.readParcelable(classLoader);
             int handlePresentation = source.readInt();
@@ -264,10 +271,10 @@
             source.readList(conferenceableCallIds, classLoader);
             Bundle extras = source.readParcelable(classLoader);
             return new ParcelableCall(id, state, disconnectCauseCode, disconnectCauseMsg,
-                    cannedSmsResponses, capabilities, connectTimeMillis, handle, handlePresentation,
-                    callerDisplayName, callerDisplayNamePresentation, gatewayInfo,
-                    accountHandle, videoCallProvider, parentCallId, childCallIds, statusHints,
-                    videoState, conferenceableCallIds, extras);
+                    cannedSmsResponses, capabilities, properties, connectTimeMillis, handle,
+                    handlePresentation, callerDisplayName, callerDisplayNamePresentation,
+                    gatewayInfo, accountHandle, videoCallProvider, parentCallId, childCallIds,
+                    statusHints, videoState, conferenceableCallIds, extras);
         }
 
         @Override
@@ -291,6 +298,7 @@
         destination.writeString(mDisconnectCauseMsg);
         destination.writeList(mCannedSmsResponses);
         destination.writeInt(mCapabilities);
+        destination.writeInt(mProperties);
         destination.writeLong(mConnectTimeMillis);
         destination.writeParcelable(mHandle, 0);
         destination.writeInt(mHandlePresentation);
diff --git a/telecomm/java/android/telecomm/Phone.java b/telecomm/java/android/telecomm/Phone.java
index e125342..d90d954 100644
--- a/telecomm/java/android/telecomm/Phone.java
+++ b/telecomm/java/android/telecomm/Phone.java
@@ -20,7 +20,6 @@
 import android.app.PendingIntent;
 import android.util.ArrayMap;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -83,7 +82,7 @@
 
     // A List allows us to keep the Calls in a stable iteration order so that casually developed
     // user interface components do not incur any spurious jank
-    private final List<Call> mCalls = new ArrayList<>();
+    private final List<Call> mCalls = new CopyOnWriteArrayList<>();
 
     // An unmodifiable view of the above List can be safely shared with subclass implementations
     private final List<Call> mUnmodifiableCalls = Collections.unmodifiableList(mCalls);
@@ -160,6 +159,18 @@
     }
 
     /**
+     * Called to destroy the phone and cleanup any lingering calls.
+     * @hide
+     */
+    final void destroy() {
+        for (Call call : mCalls) {
+            if (call.getState() != Call.STATE_DISCONNECTED) {
+                call.internalSetDisconnected();
+            }
+        }
+    }
+
+    /**
      * Adds a listener to this {@code Phone}.
      *
      * @param listener A {@code Listener} object.
diff --git a/telecomm/java/android/telecomm/PhoneCapabilities.java b/telecomm/java/android/telecomm/PhoneCapabilities.java
index 45168d5..0c6a1ef 100644
--- a/telecomm/java/android/telecomm/PhoneCapabilities.java
+++ b/telecomm/java/android/telecomm/PhoneCapabilities.java
@@ -19,7 +19,6 @@
 /**
  * Defines capabilities a phone call can support, such as conference calling and video telephony.
  * Also defines properties of a phone call, such as whether it is using VoLTE technology.
-
  */
 public final class PhoneCapabilities {
     /** Call can currently be put on hold or unheld. */
diff --git a/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl b/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl
index 42c77d7..0ab7564 100644
--- a/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl
+++ b/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl
@@ -20,6 +20,8 @@
 
 /**
  * Simple response callback object.
+ *
+ * {@hide}
  */
 oneway interface RemoteServiceCallback {
     void onError();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 71b796a..cdee3de 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3105,13 +3105,13 @@
 
     /** @hide */
     @SystemApi
-    public List<String> getCarrierPackageNamesForBroadcastIntent(Intent intent) {
+    public List<String> getCarrierPackageNamesForIntent(Intent intent) {
         try {
-            return getITelephony().getCarrierPackageNamesForBroadcastIntent(intent);
+            return getITelephony().getCarrierPackageNamesForIntent(intent);
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "getCarrierPackageNamesForBroadcastIntent RemoteException", ex);
+            Rlog.e(TAG, "getCarrierPackageNamesForIntent RemoteException", ex);
         } catch (NullPointerException ex) {
-            Rlog.e(TAG, "getCarrierPackageNamesForBroadcastIntent NPE", ex);
+            Rlog.e(TAG, "getCarrierPackageNamesForIntent NPE", ex);
         }
         return null;
     }
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index c9c4586..d93c282 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -40,8 +40,6 @@
 import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
 import android.telephony.SubscriptionManager;
 
-import android.telephony.TelephonyManager;
-
 import java.util.Locale;
 
 
@@ -219,7 +217,7 @@
                 columnIndex = getColumnIndexForPersonId(contactRef, cursor);
                 if (columnIndex != -1) {
                     final long contactId = cursor.getLong(columnIndex);
-                    if (contactId != 0 && !Contacts.isCorpContactId(contactId)) {
+                    if (contactId != 0 && !Contacts.isEnterpriseContactId(contactId)) {
                         info.contactIdOrZero = contactId;
                         if (VDBG) {
                             Rlog.v(TAG, "==> got info.contactIdOrZero: " + info.contactIdOrZero);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b1c3c4a..5c3dcdb 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -710,12 +710,12 @@
      * Returns the package name of the carrier apps that should handle the input intent.
      *
      * @param packageManager PackageManager for getting receivers.
-     * @param intent Intent that will be broadcast.
+     * @param intent Intent that will be sent.
      * @return list of carrier app package names that can handle the intent.
      *         Returns null if there is an error and an empty list if there
      *         are no matching packages.
      */
-    List<String> getCarrierPackageNamesForBroadcastIntent(in Intent intent);
+    List<String> getCarrierPackageNamesForIntent(in Intent intent);
 
     /**
      * Set whether Android should display a simplified Mobile Network Settings UI.
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index ea0db56..e03b9c8 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -366,15 +366,11 @@
                     if (recent.id >= 0) {
                         // Stack on top.
                         intent.putExtra(DocActivity.LABEL, "Stacked");
-                        task.startActivity(ActivityTestMain.this, intent, null);
                     } else {
                         // Start root activity.
-                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
-                                | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
-                                | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
                         intent.putExtra(DocActivity.LABEL, "New Root");
-                        task.startActivity(ActivityTestMain.this, intent, null);
                     }
+                    task.startActivity(ActivityTestMain.this, intent, null);
                 }
                 return true;
             }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
index a81e063..afd6a8d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.test.hwui;
 
-import android.animation.TimeInterpolator;
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -28,11 +27,6 @@
 import android.view.HardwareCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.OvershootInterpolator;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
 import android.widget.LinearLayout;
 import android.widget.LinearLayout.LayoutParams;
 import android.widget.ProgressBar;
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
index 526ea5d..50633db 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
@@ -21,7 +21,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.media.browse.MediaBrowserService;
+import android.service.media.MediaBrowserService;
 import android.os.Bundle;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentTransaction;
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
index 2fc77dc..64602d52 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
@@ -22,8 +22,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.media.browse.MediaBrowser;
-import android.media.browse.MediaBrowserItem;
-import android.media.browse.MediaBrowserService;
+import android.service.media.MediaBrowserService;
 import android.os.Bundle;
 import android.net.Uri;
 import android.support.v4.app.FragmentActivity;
@@ -57,9 +56,9 @@
     private MediaBrowser mBrowser;
 
     private static class Item {
-        final MediaBrowserItem media;
+        final MediaBrowser.MediaItem media;
 
-        Item(MediaBrowserItem m) {
+        Item(MediaBrowser.MediaItem m) {
             this.media = m;
         }
     }
@@ -103,13 +102,13 @@
         final Item item = mItems.get(position);
 
         Log.i("BrowserListFragment", "Item clicked: " + position + " -- "
-                + mAdapter.getItem(position).media.getUri());
+                + mAdapter.getItem(position).media.getDescription().getIconUri());
 
         final BrowserListFragment fragment = new BrowserListFragment();
 
         final Bundle args = new Bundle();
         args.putParcelable(BrowserListFragment.ARG_COMPONENT, mComponent);
-        args.putParcelable(BrowserListFragment.ARG_URI, item.media.getUri());
+        args.putParcelable(BrowserListFragment.ARG_URI, item.media.getDescription().getIconUri());
         fragment.setArguments(args);
 
         getFragmentManager().beginTransaction()
@@ -130,7 +129,8 @@
             }
             mBrowser.subscribe(mUri, new MediaBrowser.SubscriptionCallback() {
                     @Override
-                    public void onChildrenLoaded(Uri parentUri, List<MediaBrowserItem> children) {
+                    public void onChildrenLoaded(Uri parentUri,
+                            List<MediaBrowser.MediaItem> children) {
                         Log.d(TAG, "onChildrenLoaded parentUri=" + parentUri
                                 + " children= " + children);
                         mItems.clear();
@@ -197,7 +197,7 @@
 
             final TextView tv = (TextView)convertView;
             final Item item = mItems.get(position);
-            tv.setText(item.media.getTitle());
+            tv.setText(item.media.getDescription().getTitle());
 
             return convertView;
         }
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
index 937f1e6..845db6c 100644
--- a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
@@ -25,13 +25,14 @@
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
 import android.media.AudioManager;
+import android.media.MediaDescription;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaPlayer.OnPreparedListener;
-import android.media.browse.MediaBrowserItem;
-import android.media.browse.MediaBrowserService;
-import android.media.browse.MediaBrowserService.BrowserRoot;
+import android.media.browse.MediaBrowser;
+import android.service.media.MediaBrowserService;
+import android.service.media.MediaBrowserService.BrowserRoot;
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
@@ -122,17 +123,19 @@
 
     @Override
     public void onLoadChildren(final Uri parentUri,
-            final Result<List<MediaBrowserItem>> result) {
+            final Result<List<MediaBrowser.MediaItem>> result) {
         new Handler().postDelayed(new Runnable() {
                 public void run() {
-                    final ArrayList<MediaBrowserItem> list = new ArrayList();
+                    final ArrayList<MediaBrowser.MediaItem> list = new ArrayList();
 
                     for (int i=0; i<10; i++) {
-                        list.add(new MediaBrowserItem.Builder(
-                                    Uri.withAppendedPath(BASE_URI, Integer.toString(i)),
-                                    MediaBrowserItem.FLAG_BROWSABLE, "Title " + i)
-                                .setSummary("Summary " + i)
-                                .build());
+                        MediaDescription.Builder bob = new MediaDescription.Builder();
+                        bob.setTitle("Title " + i);
+                        bob.setSubtitle("Summary " + i);
+                        bob.setMediaId(Uri.withAppendedPath(BASE_URI,
+                                Integer.toString(i)).toString());
+                        list.add(new MediaBrowser.MediaItem(MediaBrowser.MediaItem.FLAG_BROWSABLE,
+                                bob.build()));
                     }
 
                     result.sendResult(list);
@@ -141,11 +144,6 @@
         result.detach();
     }
 
-    @Override
-    public void onLoadIcon(Uri uri, int width, int height, Result<Bitmap> result) {
-        result.sendResult(null);
-    }
-
     /*
     @Override
     public void query(final Query query, final IMetadataResultHandler metadataResultHandler,
diff --git a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
index a5bcda5..d1172ac 100644
--- a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
+++ b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
@@ -12,6 +12,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Bitmap;
+import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
@@ -185,10 +186,10 @@
             text = "Empty metadata!";
             art = null;
         } else {
-            MediaMetadata.Description description = mMetadata.getDescription();
+            MediaDescription description = mMetadata.getDescription();
             title = description.getTitle();
             text = description.getSubtitle();
-            art = description.getIcon();
+            art = description.getIconBitmap();
         }
 
         String playPauseLabel = "";
diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
index 0cab10de..2ec620b 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -77,9 +77,9 @@
                 mProx.release();
             }
         },
-        new Test("Disable proximity (WAIT_FOR_PROXIMITY_NEGATIVE)") {
+        new Test("Disable proximity (WAIT_FOR_DISTANT_PROXIMITY") {
             public void run() {
-                mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
+                mProx.release(PowerManager.WAIT_FOR_DISTANT_PROXIMITY);
             }
         },
         new Test("Enable proximity, wait 5 seconds then disable") {
@@ -93,13 +93,13 @@
                 }, 5000);
             }
         },
-        new Test("Enable proximity, wait 5 seconds then disable  (WAIT_FOR_PROXIMITY_NEGATIVE)") {
+        new Test("Enable proximity, wait 5 seconds then disable  (WAIT_FOR_DISTANT_PROXIMITY)") {
             public void run() {
                 mProx.acquire();
                 mHandler.postDelayed(new Runnable() {
                     @Override
                     public void run() {
-                        mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
+                        mProx.release(PowerManager.WAIT_FOR_DISTANT_PROXIMITY);
                     }
                 }, 5000);
             }
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index e1a579c..1f01461 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -92,8 +92,7 @@
                 break;
             case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
                 Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
-                Intent enroll = mHotwordDetector.getManageIntent(
-                        AlwaysOnHotwordDetector.MANAGE_ACTION_ENROLL);
+                Intent enroll = mHotwordDetector.createIntentToEnroll();
                 Log.i(TAG, "Need to enroll with " + enroll);
                 break;
             case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index b44e2d1..117fc24 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1594,6 +1594,11 @@
     return mIncludedAssets.getResources(false);
 }
 
+AssetManager& AaptAssets::getAssetManager()
+{
+    return mIncludedAssets;
+}
+
 void AaptAssets::print(const String8& prefix) const
 {
     String8 innerPrefix(prefix);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 0c2576a..3fc9f81 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -561,6 +561,7 @@
     status_t buildIncludedResources(Bundle* bundle);
     status_t addIncludedResources(const sp<AaptFile>& file);
     const ResTable& getIncludedResources() const;
+    AssetManager& getAssetManager();
 
     void print(const String8& prefix) const;
 
diff --git a/tools/aapt/AaptXml.cpp b/tools/aapt/AaptXml.cpp
new file mode 100644
index 0000000..708e405
--- /dev/null
+++ b/tools/aapt/AaptXml.cpp
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+
+#include "AaptXml.h"
+
+using namespace android;
+
+namespace AaptXml {
+
+static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
+        String8* outError) {
+    Res_value value;
+    if (tree.getAttributeValue(attrIndex, &value) < 0) {
+        if (outError != NULL) {
+            *outError = "could not find attribute at index";
+        }
+        return String8();
+    }
+
+    if (value.dataType != Res_value::TYPE_STRING) {
+        if (outError != NULL) {
+            *outError = "attribute is not a string value";
+        }
+        return String8();
+    }
+
+    size_t len;
+    const uint16_t* str = tree.getAttributeStringValue(attrIndex, &len);
+    return str ? String8(str, len) : String8();
+}
+
+static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
+    int32_t defValue, String8* outError) {
+    Res_value value;
+    if (tree.getAttributeValue(attrIndex, &value) < 0) {
+        if (outError != NULL) {
+            *outError = "could not find attribute at index";
+        }
+        return defValue;
+    }
+
+    if (value.dataType < Res_value::TYPE_FIRST_INT
+            || value.dataType > Res_value::TYPE_LAST_INT) {
+        if (outError != NULL) {
+            *outError = "attribute is not an integer value";
+        }
+        return defValue;
+    }
+    return value.data;
+}
+
+
+ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) {
+    size_t attrCount = tree.getAttributeCount();
+    for (size_t i = 0; i < attrCount; i++) {
+        if (tree.getAttributeNameResID(i) == attrRes) {
+            return (ssize_t)i;
+        }
+    }
+    return -1;
+}
+
+String8 getAttribute(const ResXMLTree& tree, const char* ns,
+        const char* attr, String8* outError) {
+    ssize_t idx = tree.indexOfAttribute(ns, attr);
+    if (idx < 0) {
+        return String8();
+    }
+    return getStringAttributeAtIndex(tree, idx, outError);
+}
+
+String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) {
+    ssize_t idx = indexOfAttribute(tree, attrRes);
+    if (idx < 0) {
+        return String8();
+    }
+    return getStringAttributeAtIndex(tree, idx, outError);
+}
+
+String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
+        uint32_t attrRes, String8* outError) {
+    ssize_t idx = indexOfAttribute(tree, attrRes);
+    if (idx < 0) {
+        return String8();
+    }
+    Res_value value;
+    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
+        if (value.dataType == Res_value::TYPE_STRING) {
+            size_t len;
+            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
+            return str ? String8(str, len) : String8();
+        }
+        resTable.resolveReference(&value, 0);
+        if (value.dataType != Res_value::TYPE_STRING) {
+            if (outError != NULL) {
+                *outError = "attribute is not a string value";
+            }
+            return String8();
+        }
+    }
+    size_t len;
+    const Res_value* value2 = &value;
+    const char16_t* str = resTable.valueToString(value2, 0, NULL, &len);
+    return str ? String8(str, len) : String8();
+}
+
+int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
+        const char* attr, int32_t defValue, String8* outError) {
+    ssize_t idx = tree.indexOfAttribute(ns, attr);
+    if (idx < 0) {
+        return defValue;
+    }
+    return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
+}
+
+int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
+        String8* outError) {
+    ssize_t idx = indexOfAttribute(tree, attrRes);
+    if (idx < 0) {
+        return defValue;
+    }
+    return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
+}
+
+int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
+        uint32_t attrRes, int32_t defValue, String8* outError) {
+    ssize_t idx = indexOfAttribute(tree, attrRes);
+    if (idx < 0) {
+        return defValue;
+    }
+    Res_value value;
+    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
+        if (value.dataType == Res_value::TYPE_REFERENCE) {
+            resTable.resolveReference(&value, 0);
+        }
+        if (value.dataType < Res_value::TYPE_FIRST_INT
+                || value.dataType > Res_value::TYPE_LAST_INT) {
+            if (outError != NULL) {
+                *outError = "attribute is not an integer value";
+            }
+            return defValue;
+        }
+    }
+    return value.data;
+}
+
+void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
+        uint32_t attrRes, Res_value* outValue, String8* outError) {
+    ssize_t idx = indexOfAttribute(tree, attrRes);
+    if (idx < 0) {
+        if (outError != NULL) {
+            *outError = "attribute could not be found";
+        }
+        return;
+    }
+    if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
+        if (outValue->dataType == Res_value::TYPE_REFERENCE) {
+            resTable.resolveReference(outValue, 0);
+        }
+        // The attribute was found and was resolved if need be.
+        return;
+    }
+    if (outError != NULL) {
+        *outError = "error getting resolved resource attribute";
+    }
+}
+
+} // namespace AaptXml
diff --git a/tools/aapt/AaptXml.h b/tools/aapt/AaptXml.h
new file mode 100644
index 0000000..16977f3
--- /dev/null
+++ b/tools/aapt/AaptXml.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef __AAPT_XML_H
+#define __AAPT_XML_H
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+
+/**
+ * Utility methods for dealing with ResXMLTree.
+ */
+namespace AaptXml {
+
+/**
+ * Returns the index of the attribute, or < 0 if it was not found.
+ */
+ssize_t indexOfAttribute(const android::ResXMLTree& tree, uint32_t attrRes);
+
+/**
+ * Returns the string value for the specified attribute.
+ * The string must be present in the ResXMLTree's string pool (inline in the XML).
+ */
+android::String8 getAttribute(const android::ResXMLTree& tree, const char* ns,
+        const char* attr, android::String8* outError = NULL);
+
+/**
+ * Returns the string value for the specified attribute, or an empty string
+ * if the attribute does not exist.
+ * The string must be present in the ResXMLTree's string pool (inline in the XML).
+ */
+android::String8 getAttribute(const android::ResXMLTree& tree, uint32_t attrRes,
+        android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+int32_t getIntegerAttribute(const android::ResXMLTree& tree, const char* ns,
+        const char* attr, int32_t defValue = -1, android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+inline int32_t getIntegerAttribute(const android::ResXMLTree& tree, const char* ns,
+        const char* attr, android::String8* outError) {
+    return getIntegerAttribute(tree, ns, attr, -1, outError);
+}
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+int32_t getIntegerAttribute(const android::ResXMLTree& tree, uint32_t attrRes,
+        int32_t defValue = -1, android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+inline int32_t getIntegerAttribute(const android::ResXMLTree& tree, uint32_t attrRes,
+        android::String8* outError) {
+    return getIntegerAttribute(tree, attrRes, -1, outError);
+}
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer may be a resource in the supplied ResTable.
+ */
+int32_t getResolvedIntegerAttribute(const android::ResTable& resTable,
+        const android::ResXMLTree& tree, uint32_t attrRes, int32_t defValue = -1,
+        android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer may be a resource in the supplied ResTable.
+ */
+inline int32_t getResolvedIntegerAttribute(const android::ResTable& resTable,
+        const android::ResXMLTree& tree, uint32_t attrRes,
+        android::String8* outError) {
+    return getResolvedIntegerAttribute(resTable, tree, attrRes, -1, outError);
+}
+
+/**
+ * Returns the string value for the specified attribute, or an empty string
+ * if the attribute does not exist.
+ * The string may be a resource in the supplied ResTable.
+ */
+android::String8 getResolvedAttribute(const android::ResTable& resTable,
+        const android::ResXMLTree& tree, uint32_t attrRes,
+        android::String8* outError = NULL);
+
+/**
+ * Returns the resource for the specified attribute in the outValue parameter.
+ * The resource may be a resource in the supplied ResTable.
+ */
+void getResolvedResourceAttribute(const android::ResTable& resTable,
+        const android::ResXMLTree& tree, uint32_t attrRes, android::Res_value* outValue,
+        android::String8* outError = NULL);
+
+} // namespace AaptXml
+
+#endif // __AAPT_XML_H
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 4ce5045..2cbabe1 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -28,6 +28,7 @@
     AaptAssets.cpp \
     AaptConfig.cpp \
     AaptUtil.cpp \
+    AaptXml.cpp \
     ApkBuilder.cpp \
     Command.cpp \
     CrunchCache.cpp \
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index af49461..9bed899 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -130,6 +130,10 @@
     void setErrorOnFailedInsert(bool val) { mErrorOnFailedInsert = val; }
     bool getErrorOnMissingConfigEntry() { return mErrorOnMissingConfigEntry; }
     void setErrorOnMissingConfigEntry(bool val) { mErrorOnMissingConfigEntry = val; }
+    const android::String8& getPlatformBuildVersionCode() { return mPlatformVersionCode; }
+    void setPlatformBuildVersionCode(const android::String8& code) { mPlatformVersionCode = code; }
+    const android::String8& getPlatformBuildVersionName() { return mPlatformVersionName; }
+    void setPlatformBuildVersionName(const android::String8& name) { mPlatformVersionName = name; }
 
     bool getUTF16StringsOption() {
         return mWantUTF16 || !isMinSdkAtLeast(SDK_FROYO);
@@ -323,6 +327,8 @@
     const char* mSingleCrunchInputFile;
     const char* mSingleCrunchOutputFile;
     bool        mBuildSharedLibrary;
+    android::String8 mPlatformVersionCode;
+    android::String8 mPlatformVersionName;
 
     /* file specification */
     int         mArgc;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index a0f0a08..fd660bb 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -3,6 +3,7 @@
 //
 // Android Asset Packaging Tool main entry point.
 //
+#include "AaptXml.h"
 #include "ApkBuilder.h"
 #include "Bundle.h"
 #include "Images.h"
@@ -241,162 +242,17 @@
     return result;
 }
 
-static ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
-{
-    size_t N = tree.getAttributeCount();
-    for (size_t i=0; i<N; i++) {
-        if (tree.getAttributeNameResID(i) == attrRes) {
-            return (ssize_t)i;
-        }
-    }
-    return -1;
-}
-
-String8 getAttribute(const ResXMLTree& tree, const char* ns,
-                            const char* attr, String8* outError)
-{
-    ssize_t idx = tree.indexOfAttribute(ns, attr);
-    if (idx < 0) {
-        return String8();
-    }
-    Res_value value;
-    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
-        if (value.dataType != Res_value::TYPE_STRING) {
-            if (outError != NULL) {
-                *outError = "attribute is not a string value";
-            }
-            return String8();
-        }
-    }
-    size_t len;
-    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
-    return str ? String8(str, len) : String8();
-}
-
-static String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
-{
-    ssize_t idx = indexOfAttribute(tree, attrRes);
-    if (idx < 0) {
-        return String8();
-    }
-    Res_value value;
-    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
-        if (value.dataType != Res_value::TYPE_STRING) {
-            if (outError != NULL) {
-                *outError = "attribute is not a string value";
-            }
-            return String8();
-        }
-    }
-    size_t len;
-    const uint16_t* str = tree.getAttributeStringValue(idx, &len);
-    return str ? String8(str, len) : String8();
-}
-
-static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
-        String8* outError, int32_t defValue = -1)
-{
-    ssize_t idx = indexOfAttribute(tree, attrRes);
-    if (idx < 0) {
-        return defValue;
-    }
-    Res_value value;
-    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
-        if (value.dataType < Res_value::TYPE_FIRST_INT
-                || value.dataType > Res_value::TYPE_LAST_INT) {
-            if (outError != NULL) {
-                *outError = "attribute is not an integer value";
-            }
-            return defValue;
-        }
-    }
-    return value.data;
-}
-
-static int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
-        uint32_t attrRes, String8* outError, int32_t defValue = -1)
-{
-    ssize_t idx = indexOfAttribute(tree, attrRes);
-    if (idx < 0) {
-        return defValue;
-    }
-    Res_value value;
-    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
-        if (value.dataType == Res_value::TYPE_REFERENCE) {
-            resTable->resolveReference(&value, 0);
-        }
-        if (value.dataType < Res_value::TYPE_FIRST_INT
-                || value.dataType > Res_value::TYPE_LAST_INT) {
-            if (outError != NULL) {
-                *outError = "attribute is not an integer value";
-            }
-            return defValue;
-        }
-    }
-    return value.data;
-}
-
-static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
-        uint32_t attrRes, String8* outError)
-{
-    ssize_t idx = indexOfAttribute(tree, attrRes);
-    if (idx < 0) {
-        return String8();
-    }
-    Res_value value;
-    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
-        if (value.dataType == Res_value::TYPE_STRING) {
-            size_t len;
-            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
-            return str ? String8(str, len) : String8();
-        }
-        resTable->resolveReference(&value, 0);
-        if (value.dataType != Res_value::TYPE_STRING) {
-            if (outError != NULL) {
-                *outError = "attribute is not a string value";
-            }
-            return String8();
-        }
-    }
-    size_t len;
-    const Res_value* value2 = &value;
-    const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
-    return str ? String8(str, len) : String8();
-}
-
-static void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable,
-        const ResXMLTree& tree, uint32_t attrRes, String8* outError)
-{
-    ssize_t idx = indexOfAttribute(tree, attrRes);
-    if (idx < 0) {
-        if (outError != NULL) {
-            *outError = "attribute could not be found";
-        }
-        return;
-    }
-    if (tree.getAttributeValue(idx, value) != NO_ERROR) {
-        if (value->dataType == Res_value::TYPE_REFERENCE) {
-            resTable->resolveReference(value, 0);
-        }
-        // The attribute was found and was resolved if need be.
-        return;
-    }
-    if (outError != NULL) {
-        *outError = "error getting resolved resource attribute";
-    }
-}
-
-static void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree,
+static void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
         uint32_t attrRes, String8 attrLabel, String8* outError)
 {
     Res_value value;
-    getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError);
+    AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
     if (*outError != "") {
         *outError = "error print resolved resource attribute";
         return;
     }
     if (value.dataType == Res_value::TYPE_STRING) {
-        String8 result = getResolvedAttribute(resTable, tree, attrRes, outError);
+        String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError);
         printf("%s='%s'", attrLabel.string(),
                 ResTable::normalizeForOutput(result.string()).string());
     } else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
@@ -488,10 +344,10 @@
         }
         String8 tag(ctag16);
         if (tag == "screen") {
-            int32_t screenSize = getIntegerAttribute(tree,
-                    SCREEN_SIZE_ATTR, NULL, -1);
-            int32_t screenDensity = getIntegerAttribute(tree,
-                    SCREEN_DENSITY_ATTR, NULL, -1);
+            int32_t screenSize = AaptXml::getIntegerAttribute(tree,
+                    SCREEN_SIZE_ATTR);
+            int32_t screenDensity = AaptXml::getIntegerAttribute(tree,
+                    SCREEN_DENSITY_ATTR);
             if (screenSize > 0 && screenDensity > 0) {
                 if (!first) {
                     printf(",");
@@ -577,7 +433,7 @@
                 }
             } else if (depth == 2 && withinApduService) {
                 if (tag == "aid-group") {
-                    String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
+                    String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error);
                     if (error != "") {
                         if (outError != NULL) *outError = error;
                         return Vector<String8>();
@@ -876,11 +732,11 @@
                         fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
                         goto bail;
                     }
-                    String8 pkg = getAttribute(tree, NULL, "package", NULL);
+                    String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
                     printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
                 } else if (depth == 2 && tag == "permission") {
                     String8 error;
-                    String8 name = getAttribute(tree, NAME_ATTR, &error);
+                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                     if (error != "") {
                         fprintf(stderr, "ERROR: %s\n", error.string());
                         goto bail;
@@ -889,14 +745,14 @@
                             ResTable::normalizeForOutput(name.string()).string());
                 } else if (depth == 2 && tag == "uses-permission") {
                     String8 error;
-                    String8 name = getAttribute(tree, NAME_ATTR, &error);
+                    String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                     if (error != "") {
                         fprintf(stderr, "ERROR: %s\n", error.string());
                         goto bail;
                     }
                     printUsesPermission(name,
-                            getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
-                            getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
+                            AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
+                            AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
                 }
             }
         } else if (strcmp("badging", option) == 0) {
@@ -1151,12 +1007,14 @@
                         fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
                         goto bail;
                     }
-                    pkg = getAttribute(tree, NULL, "package", NULL);
+                    pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
                     printf("package: name='%s' ",
                             ResTable::normalizeForOutput(pkg.string()).string());
-                    int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
+                    int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR,
+                            &error);
                     if (error != "") {
-                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
+                        fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n",
+                                error.string());
                         goto bail;
                     }
                     if (versionCode > 0) {
@@ -1164,23 +1022,29 @@
                     } else {
                         printf("versionCode='' ");
                     }
-                    String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
+                    String8 versionName = AaptXml::getResolvedAttribute(res, tree,
+                            VERSION_NAME_ATTR, &error);
                     if (error != "") {
-                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
+                        fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n",
+                                error.string());
                         goto bail;
                     }
                     printf("versionName='%s'",
                             ResTable::normalizeForOutput(versionName.string()).string());
 
-                    String8 splitName = getAttribute(tree, NULL, "split", NULL);
+                    String8 splitName = AaptXml::getAttribute(tree, NULL, "split");
                     if (!splitName.isEmpty()) {
                         printf(" split='%s'", ResTable::normalizeForOutput(
                                     splitName.string()).string());
                     }
+
+                    int32_t platformVersionCode = AaptXml::getIntegerAttribute(tree, NULL,
+                            "platformBuildVersionCode");
+                    printf(" platformBuildVersionCode='%d'", platformVersionCode);
                     printf("\n");
 
-                    int32_t installLocation = getResolvedIntegerAttribute(&res, tree,
-                            INSTALL_LOCATION_ATTR, &error, -1);
+                    int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
+                            INSTALL_LOCATION_ATTR, &error);
                     if (error != "") {
                         fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
                                 error.string());
@@ -1215,7 +1079,8 @@
                         for (size_t i=0; i<NL; i++) {
                             const char* localeStr =  locales[i].string();
                             assets.setLocale(localeStr != NULL ? localeStr : "");
-                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+                            String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
+                                    &error);
                             if (llabel != "") {
                                 if (localeStr == NULL || strlen(localeStr) == 0) {
                                     label = llabel;
@@ -1236,7 +1101,8 @@
                         for (size_t i=0; i<ND; i++) {
                             tmpConfig.density = densities[i];
                             assets.setConfiguration(tmpConfig);
-                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+                            String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
+                                    &error);
                             if (icon != "") {
                                 printf("application-icon-%d:'%s'\n", densities[i],
                                         ResTable::normalizeForOutput(icon.string()).string());
@@ -1244,14 +1110,17 @@
                         }
                         assets.setConfiguration(config);
 
-                        String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+                        String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error);
                         if (error != "") {
-                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
+                            fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
+                                    error.string());
                             goto bail;
                         }
-                        int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
+                        int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0,
+                                &error);
                         if (error != "") {
-                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
+                            fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n",
+                                    error.string());
                             goto bail;
                         }
                         printf("application: label='%s' ",
@@ -1261,9 +1130,11 @@
                             printf("testOnly='%d'\n", testOnly);
                         }
 
-                        int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
+                        int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree,
+                                DEBUGGABLE_ATTR, 0, &error);
                         if (error != "") {
-                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
+                            fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n",
+                                    error.string());
                             goto bail;
                         }
                         if (debuggable != 0) {
@@ -1284,10 +1155,11 @@
                             }
                         }
                     } else if (tag == "uses-sdk") {
-                        int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
+                        int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
                         if (error != "") {
                             error = "";
-                            String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
+                            String8 name = AaptXml::getResolvedAttribute(res, tree,
+                                    MIN_SDK_VERSION_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
                                         error.string());
@@ -1300,14 +1172,15 @@
                             targetSdk = code;
                             printf("sdkVersion:'%d'\n", code);
                         }
-                        code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
+                        code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR);
                         if (code != -1) {
                             printf("maxSdkVersion:'%d'\n", code);
                         }
-                        code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
+                        code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
                         if (error != "") {
                             error = "";
-                            String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
+                            String8 name = AaptXml::getResolvedAttribute(res, tree,
+                                    TARGET_SDK_VERSION_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
                                         error.string());
@@ -1323,16 +1196,16 @@
                             printf("targetSdkVersion:'%d'\n", code);
                         }
                     } else if (tag == "uses-configuration") {
-                        int32_t reqTouchScreen = getIntegerAttribute(tree,
-                                REQ_TOUCH_SCREEN_ATTR, NULL, 0);
-                        int32_t reqKeyboardType = getIntegerAttribute(tree,
-                                REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
-                        int32_t reqHardKeyboard = getIntegerAttribute(tree,
-                                REQ_HARD_KEYBOARD_ATTR, NULL, 0);
-                        int32_t reqNavigation = getIntegerAttribute(tree,
-                                REQ_NAVIGATION_ATTR, NULL, 0);
-                        int32_t reqFiveWayNav = getIntegerAttribute(tree,
-                                REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
+                        int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree,
+                                REQ_TOUCH_SCREEN_ATTR, 0);
+                        int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree,
+                                REQ_KEYBOARD_TYPE_ATTR, 0);
+                        int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree,
+                                REQ_HARD_KEYBOARD_ATTR, 0);
+                        int32_t reqNavigation = AaptXml::getIntegerAttribute(tree,
+                                REQ_NAVIGATION_ATTR, 0);
+                        int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree,
+                                REQ_FIVE_WAY_NAV_ATTR, 0);
                         printf("uses-configuration:");
                         if (reqTouchScreen != 0) {
                             printf(" reqTouchScreen='%d'", reqTouchScreen);
@@ -1353,26 +1226,26 @@
                     } else if (tag == "supports-input") {
                         withinSupportsInput = true;
                     } else if (tag == "supports-screens") {
-                        smallScreen = getIntegerAttribute(tree,
-                                SMALL_SCREEN_ATTR, NULL, 1);
-                        normalScreen = getIntegerAttribute(tree,
-                                NORMAL_SCREEN_ATTR, NULL, 1);
-                        largeScreen = getIntegerAttribute(tree,
-                                LARGE_SCREEN_ATTR, NULL, 1);
-                        xlargeScreen = getIntegerAttribute(tree,
-                                XLARGE_SCREEN_ATTR, NULL, 1);
-                        anyDensity = getIntegerAttribute(tree,
-                                ANY_DENSITY_ATTR, NULL, 1);
-                        requiresSmallestWidthDp = getIntegerAttribute(tree,
-                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
-                        compatibleWidthLimitDp = getIntegerAttribute(tree,
-                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
-                        largestWidthLimitDp = getIntegerAttribute(tree,
-                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
+                        smallScreen = AaptXml::getIntegerAttribute(tree,
+                                SMALL_SCREEN_ATTR, 1);
+                        normalScreen = AaptXml::getIntegerAttribute(tree,
+                                NORMAL_SCREEN_ATTR, 1);
+                        largeScreen = AaptXml::getIntegerAttribute(tree,
+                                LARGE_SCREEN_ATTR, 1);
+                        xlargeScreen = AaptXml::getIntegerAttribute(tree,
+                                XLARGE_SCREEN_ATTR, 1);
+                        anyDensity = AaptXml::getIntegerAttribute(tree,
+                                ANY_DENSITY_ATTR, 1);
+                        requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree,
+                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0);
+                        compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree,
+                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0);
+                        largestWidthLimitDp = AaptXml::getIntegerAttribute(tree,
+                                LARGEST_WIDTH_LIMIT_DP_ATTR, 0);
                     } else if (tag == "feature-group") {
                         withinFeatureGroup = true;
                         FeatureGroup group;
-                        group.label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+                        group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error);
                         if (error != "") {
                             fprintf(stderr, "ERROR getting 'android:label' attribute:"
                                     " %s\n", error.string());
@@ -1381,17 +1254,17 @@
                         featureGroups.add(group);
 
                     } else if (tag == "uses-feature") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
-                            int req = getIntegerAttribute(tree,
-                                    REQUIRED_ATTR, NULL, 1);
+                            int req = AaptXml::getIntegerAttribute(tree,
+                                    REQUIRED_ATTR, 1);
 
                             commonFeatures.features.add(name, req);
                             if (req) {
                                 addParentFeatures(&commonFeatures, name);
                             }
                         } else {
-                            int vers = getIntegerAttribute(tree,
+                            int vers = AaptXml::getIntegerAttribute(tree,
                                     GL_ES_VERSION_ATTR, &error);
                             if (error == "") {
                                 if (vers > commonFeatures.openGLESVersion) {
@@ -1400,7 +1273,7 @@
                             }
                         }
                     } else if (tag == "uses-permission") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
                             if (name == "android.permission.CAMERA") {
                                 addImpliedFeature(&impliedFeatures, "android.hardware.camera",
@@ -1478,15 +1351,15 @@
                             }
 
                             printUsesPermission(name,
-                                    getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
-                                    getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
+                                    AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
+                                    AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
                        } else {
                             fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
                                     error.string());
                             goto bail;
                         }
                     } else if (tag == "uses-package") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
                             printf("uses-package:'%s'\n",
                                     ResTable::normalizeForOutput(name.string()).string());
@@ -1496,7 +1369,7 @@
                                 goto bail;
                         }
                     } else if (tag == "original-package") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
                             printf("original-package:'%s'\n",
                                     ResTable::normalizeForOutput(name.string()).string());
@@ -1506,7 +1379,7 @@
                                 goto bail;
                         }
                     } else if (tag == "supports-gl-texture") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
                             printf("supports-gl-texture:'%s'\n",
                                     ResTable::normalizeForOutput(name.string()).string());
@@ -1524,9 +1397,9 @@
                         }
                         depth--;
                     } else if (tag == "package-verifier") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
-                            String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
+                            String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error);
                             if (publicKey != "" && error == "") {
                                 printf("package-verifier: name='%s' publicKey='%s'\n",
                                         ResTable::normalizeForOutput(name.string()).string(),
@@ -1553,35 +1426,38 @@
                     if (withinApplication) {
                         if(tag == "activity") {
                             withinActivity = true;
-                            activityName = getAttribute(tree, NAME_ATTR, &error);
+                            activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
                                         error.string());
                                 goto bail;
                             }
 
-                            activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+                            activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
+                                    &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
                                         error.string());
                                 goto bail;
                             }
 
-                            activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+                            activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
+                                    &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
                                         error.string());
                                 goto bail;
                             }
 
-                            activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
+                            activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR,
+                                    &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
                                         error.string());
                                 goto bail;
                             }
 
-                            int32_t orien = getResolvedIntegerAttribute(&res, tree,
+                            int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree,
                                     SCREEN_ORIENTATION_ATTR, &error);
                             if (error == "") {
                                 if (orien == 0 || orien == 6 || orien == 8) {
@@ -1595,21 +1471,21 @@
                                 }
                             }
                         } else if (tag == "uses-library") {
-                            String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
+                            String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr,
                                         "ERROR getting 'android:name' attribute for uses-library"
                                         " %s\n", error.string());
                                 goto bail;
                             }
-                            int req = getIntegerAttribute(tree,
-                                    REQUIRED_ATTR, NULL, 1);
+                            int req = AaptXml::getIntegerAttribute(tree,
+                                    REQUIRED_ATTR, 1);
                             printf("uses-library%s:'%s'\n",
                                     req ? "" : "-not-required", ResTable::normalizeForOutput(
                                             libraryName.string()).string());
                         } else if (tag == "receiver") {
                             withinReceiver = true;
-                            receiverName = getAttribute(tree, NAME_ATTR, &error);
+                            receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
 
                             if (error != "") {
                                 fprintf(stderr,
@@ -1618,7 +1494,8 @@
                                 goto bail;
                             }
 
-                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
+                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
+                                    &error);
                             if (error == "") {
                                 if (permission == "android.permission.BIND_DEVICE_ADMIN") {
                                     hasBindDeviceAdminPermission = true;
@@ -1629,7 +1506,7 @@
                             }
                         } else if (tag == "service") {
                             withinService = true;
-                            serviceName = getAttribute(tree, NAME_ATTR, &error);
+                            serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
 
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:name' attribute for "
@@ -1637,7 +1514,8 @@
                                 goto bail;
                             }
 
-                            String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
+                            String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
+                                    &error);
                             if (error == "") {
                                 if (permission == "android.permission.BIND_INPUT_METHOD") {
                                     hasBindInputMethodPermission = true;
@@ -1659,22 +1537,24 @@
                         } else if (tag == "provider") {
                             withinProvider = true;
 
-                            bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error);
+                            bool exported = AaptXml::getResolvedIntegerAttribute(res, tree,
+                                    EXPORTED_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
                                         " %s\n", error.string());
                                 goto bail;
                             }
 
-                            bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree,
-                                    GRANT_URI_PERMISSIONS_ATTR, &error);
+                            bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute(
+                                    res, tree, GRANT_URI_PERMISSIONS_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
                                         " %s\n", error.string());
                                 goto bail;
                             }
 
-                            String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error);
+                            String8 permission = AaptXml::getResolvedAttribute(res, tree,
+                                    PERMISSION_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
                                         " %s\n", error.string());
@@ -1685,7 +1565,8 @@
                                 permission == "android.permission.MANAGE_DOCUMENTS";
 
                         } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
-                            String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
+                            String8 metaDataName = AaptXml::getResolvedAttribute(res, tree,
+                                    NAME_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:name' attribute for "
                                         "meta-data:%s\n", error.string());
@@ -1693,12 +1574,12 @@
                             }
                             printf("meta-data: name='%s' ",
                                     ResTable::normalizeForOutput(metaDataName.string()).string());
-                            printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"),
+                            printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"),
                                     &error);
                             if (error != "") {
                                 // Try looking for a RESOURCE_ATTR
                                 error = "";
-                                printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR,
+                                printResolvedResourceAttribute(res, tree, RESOURCE_ATTR,
                                         String8("resource"), &error);
                                 if (error != "") {
                                     fprintf(stderr, "ERROR getting 'android:value' or "
@@ -1709,7 +1590,7 @@
                             }
                             printf("\n");
                         } else if (withinSupportsInput && tag == "input-type") {
-                            String8 name = getAttribute(tree, NAME_ATTR, &error);
+                            String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                             if (name != "" && error == "") {
                                 supportedInput.add(name);
                             } else {
@@ -1721,12 +1602,13 @@
                     } else if (withinFeatureGroup && tag == "uses-feature") {
                         FeatureGroup& top = featureGroups.editTop();
 
-                        String8 name = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
                             top.features.add(name, true);
                             addParentFeatures(&top, name);
                         } else {
-                            int vers = getIntegerAttribute(tree, GL_ES_VERSION_ATTR, &error);
+                            int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
+                                    &error);
                             if (error == "") {
                                 if (vers > top.openGLESVersion) {
                                     top.openGLESVersion = vers;
@@ -1754,7 +1636,7 @@
                         actCameraSecure = false;
                         catLauncher = false;
                     } else if (withinService && tag == "meta-data") {
-                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (error != "") {
                             fprintf(stderr, "ERROR getting 'android:name' attribute for"
                                     " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
@@ -1768,7 +1650,8 @@
                                 offHost = false;
                             }
 
-                            String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
+                            String8 xmlPath = AaptXml::getResolvedAttribute(res, tree,
+                                    RESOURCE_ATTR, &error);
                             if (error != "") {
                                 fprintf(stderr, "ERROR getting 'android:resource' attribute for"
                                         " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
@@ -1797,7 +1680,7 @@
                 } else if ((depth == 5) && withinIntentFilter) {
                     String8 action;
                     if (tag == "action") {
-                        action = getAttribute(tree, NAME_ATTR, &error);
+                        action = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (error != "") {
                             fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
                                     error.string());
@@ -1849,7 +1732,7 @@
                     }
 
                     if (tag == "category") {
-                        String8 category = getAttribute(tree, NAME_ATTR, &error);
+                        String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (error != "") {
                             fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
                                     error.string());
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index dd40b20..f24a023b 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -60,9 +60,6 @@
 
 int dumpResources(Bundle* bundle);
 
-String8 getAttribute(const ResXMLTree& tree, const char* ns,
-                            const char* attr, String8* outError);
-
 status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets,
                                 FILE* fp, bool includeRaw);
 #endif // __MAIN_H
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 7979a1d..5deeca2 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -4,6 +4,7 @@
 // Build resource files from raw assets.
 //
 #include "AaptAssets.h"
+#include "AaptXml.h"
 #include "CacheUpdater.h"
 #include "CrunchCache.h"
 #include "FileFinder.h"
@@ -805,6 +806,20 @@
         }
     }
 
+    if (bundle->getPlatformBuildVersionCode() != "") {
+        if (!addTagAttribute(root, "", "platformBuildVersionCode",
+                    bundle->getPlatformBuildVersionCode(), errorOnFailedInsert, true)) {
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    if (bundle->getPlatformBuildVersionName() != "") {
+        if (!addTagAttribute(root, "", "platformBuildVersionName",
+                    bundle->getPlatformBuildVersionName(), errorOnFailedInsert, true)) {
+            return UNKNOWN_ERROR;
+        }
+    }
+
     if (bundle->getDebugMode()) {
         sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
         if (application != NULL) {
@@ -881,6 +896,106 @@
     return NO_ERROR;
 }
 
+static int32_t getPlatformAssetCookie(const AssetManager& assets) {
+    // Find the system package (0x01). AAPT always generates attributes
+    // with the type 0x01, so we're looking for the first attribute
+    // resource in the system package.
+    const ResTable& table = assets.getResources(true);
+    Res_value val;
+    ssize_t idx = table.getResource(0x01010000, &val, true);
+    if (idx != NO_ERROR) {
+        // Try as a bag.
+        const ResTable::bag_entry* entry;
+        ssize_t cnt = table.lockBag(0x01010000, &entry);
+        if (cnt >= 0) {
+            idx = entry->stringBlock;
+        }
+        table.unlockBag(entry);
+    }
+
+    if (idx < 0) {
+        return 0;
+    }
+    return table.getTableCookie(idx);
+}
+
+enum {
+    VERSION_CODE_ATTR = 0x0101021b,
+    VERSION_NAME_ATTR = 0x0101021c,
+};
+
+static ssize_t extractPlatformBuildVersion(ResXMLTree& tree, Bundle* bundle) {
+    size_t len;
+    ResXMLTree::event_code_t code;
+    while ((code = tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+        if (code != ResXMLTree::START_TAG) {
+            continue;
+        }
+
+        const char16_t* ctag16 = tree.getElementName(&len);
+        if (ctag16 == NULL) {
+            fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
+            return UNKNOWN_ERROR;
+        }
+
+        String8 tag(ctag16, len);
+        if (tag != "manifest") {
+            continue;
+        }
+
+        String8 error;
+        int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
+        if (error != "") {
+            fprintf(stderr, "ERROR: failed to get platform version code\n");
+            return UNKNOWN_ERROR;
+        }
+
+        if (versionCode >= 0 && bundle->getPlatformBuildVersionCode() == "") {
+            bundle->setPlatformBuildVersionCode(String8::format("%d", versionCode));
+        }
+
+        String8 versionName = AaptXml::getAttribute(tree, VERSION_NAME_ATTR, &error);
+        if (error != "") {
+            fprintf(stderr, "ERROR: failed to get platform version name\n");
+            return UNKNOWN_ERROR;
+        }
+
+        if (versionName != "" && bundle->getPlatformBuildVersionName() == "") {
+            bundle->setPlatformBuildVersionName(versionName);
+        }
+        return NO_ERROR;
+    }
+
+    fprintf(stderr, "ERROR: no <manifest> tag found in platform AndroidManifest.xml\n");
+    return UNKNOWN_ERROR;
+}
+
+static ssize_t extractPlatformBuildVersion(AssetManager& assets, Bundle* bundle) {
+    int32_t cookie = getPlatformAssetCookie(assets);
+    if (cookie == 0) {
+        fprintf(stderr, "ERROR: Platform package not found\n");
+        return UNKNOWN_ERROR;
+    }
+
+    ResXMLTree tree;
+    Asset* asset = assets.openNonAsset(cookie, "AndroidManifest.xml", Asset::ACCESS_STREAMING);
+    if (asset == NULL) {
+        fprintf(stderr, "ERROR: Platform AndroidManifest.xml not found\n");
+        return UNKNOWN_ERROR;
+    }
+
+    ssize_t result = NO_ERROR;
+    if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) {
+        fprintf(stderr, "ERROR: Platform AndroidManifest.xml is corrupt\n");
+        result = UNKNOWN_ERROR;
+    } else {
+        result = extractPlatformBuildVersion(tree, bundle);
+    }
+
+    delete asset;
+    return result;
+}
+
 #define ASSIGN_IT(n) \
         do { \
             ssize_t index = resources->indexOfKey(String8(#n)); \
@@ -1356,6 +1471,17 @@
         return UNKNOWN_ERROR;
     }
 
+    // If we're not overriding the platform build versions,
+    // extract them from the platform APK.
+    if (packageType != ResourceTable::System &&
+            (bundle->getPlatformBuildVersionCode() == "" ||
+            bundle->getPlatformBuildVersionName() == "")) {
+        err = extractPlatformBuildVersion(assets->getAssetManager(), bundle);
+        if (err != NO_ERROR) {
+            return UNKNOWN_ERROR;
+        }
+    }
+
     const sp<AaptFile> manifestFile(androidManifestFile->getFiles().valueAt(0));
     String8 manifestPath(manifestFile->getPrintableSource());
 
@@ -2636,13 +2762,14 @@
                 fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
                 return -1;
             }
-            pkg = getAttribute(tree, NULL, "package", NULL);
+            pkg = AaptXml::getAttribute(tree, NULL, "package");
         } else if (depth == 2) {
             if (tag == "application") {
                 inApplication = true;
                 keepTag = true;
 
-                String8 agent = getAttribute(tree, "http://schemas.android.com/apk/res/android",
+                String8 agent = AaptXml::getAttribute(tree,
+                        "http://schemas.android.com/apk/res/android",
                         "backupAgent", &error);
                 if (agent.length() > 0) {
                     addProguardKeepRule(keep, agent, pkg.string(),
@@ -2658,8 +2785,8 @@
             }
         }
         if (keepTag) {
-            String8 name = getAttribute(tree, "http://schemas.android.com/apk/res/android",
-                    "name", &error);
+            String8 name = AaptXml::getAttribute(tree,
+                    "http://schemas.android.com/apk/res/android", "name", &error);
             if (error != "") {
                 fprintf(stderr, "ERROR: %s\n", error.string());
                 return -1;
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
new file mode 100644
index 0000000..fce4323
--- /dev/null
+++ b/tools/apilint/apilint.py
@@ -0,0 +1,540 @@
+#!/usr/bin/env python
+
+# 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.
+
+"""
+Enforces common Android public API design patterns.  It ignores lint messages from
+a previous API level, if provided.
+
+Usage: apilint.py current.txt
+Usage: apilint.py current.txt previous.txt
+"""
+
+import re, sys
+
+
+BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
+
+def format(fg=None, bg=None, bright=False, bold=False, dim=False, reset=False):
+    # manually derived from http://en.wikipedia.org/wiki/ANSI_escape_code#Codes
+    codes = []
+    if reset: codes.append("0")
+    else:
+        if not fg is None: codes.append("3%d" % (fg))
+        if not bg is None:
+            if not bright: codes.append("4%d" % (bg))
+            else: codes.append("10%d" % (bg))
+        if bold: codes.append("1")
+        elif dim: codes.append("2")
+        else: codes.append("22")
+    return "\033[%sm" % (";".join(codes))
+
+
+class Field():
+    def __init__(self, clazz, raw):
+        self.clazz = clazz
+        self.raw = raw.strip(" {;")
+
+        raw = raw.split()
+        self.split = list(raw)
+
+        for r in ["field", "volatile", "transient", "public", "protected", "static", "final", "deprecated"]:
+            while r in raw: raw.remove(r)
+
+        self.typ = raw[0]
+        self.name = raw[1].strip(";")
+        if len(raw) >= 4 and raw[2] == "=":
+            self.value = raw[3].strip(';"')
+        else:
+            self.value = None
+
+    def __repr__(self):
+        return self.raw
+
+
+class Method():
+    def __init__(self, clazz, raw):
+        self.clazz = clazz
+        self.raw = raw.strip(" {;")
+
+        raw = re.split("[\s(),;]+", raw)
+        for r in ["", ";"]:
+            while r in raw: raw.remove(r)
+        self.split = list(raw)
+
+        for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract"]:
+            while r in raw: raw.remove(r)
+
+        self.typ = raw[0]
+        self.name = raw[1]
+        self.args = []
+        for r in raw[2:]:
+            if r == "throws": break
+            self.args.append(r)
+
+    def __repr__(self):
+        return self.raw
+
+
+class Class():
+    def __init__(self, pkg, raw):
+        self.pkg = pkg
+        self.raw = raw.strip(" {;")
+        self.ctors = []
+        self.fields = []
+        self.methods = []
+
+        raw = raw.split()
+        self.split = list(raw)
+        if "class" in raw:
+            self.fullname = raw[raw.index("class")+1]
+        elif "interface" in raw:
+            self.fullname = raw[raw.index("interface")+1]
+
+        if "." in self.fullname:
+            self.name = self.fullname[self.fullname.rindex(".")+1:]
+        else:
+            self.name = self.fullname
+
+    def __repr__(self):
+        return self.raw
+
+
+class Package():
+    def __init__(self, raw):
+        self.raw = raw.strip(" {;")
+
+        raw = raw.split()
+        self.name = raw[raw.index("package")+1]
+
+    def __repr__(self):
+        return self.raw
+
+
+def parse_api(fn):
+    api = []
+    pkg = None
+    clazz = None
+
+    with open(fn) as f:
+        for raw in f.readlines():
+            raw = raw.rstrip()
+
+            if raw.startswith("package"):
+                pkg = Package(raw)
+            elif raw.startswith("  ") and raw.endswith("{"):
+                clazz = Class(pkg, raw)
+                api.append(clazz)
+            elif raw.startswith("    ctor"):
+                clazz.ctors.append(Method(clazz, raw))
+            elif raw.startswith("    method"):
+                clazz.methods.append(Method(clazz, raw))
+            elif raw.startswith("    field"):
+                clazz.fields.append(Field(clazz, raw))
+
+    return api
+
+
+failures = []
+
+def _fail(clazz, detail, msg):
+    """Records an API failure to be processed later."""
+    global failures
+
+    res = msg
+    if detail is not None:
+        res += "\n    in " + repr(detail)
+    res += "\n    in " + repr(clazz)
+    res += "\n    in " + repr(clazz.pkg)
+    failures.append(res)
+
+def warn(clazz, detail, msg):
+    _fail(clazz, detail, "%sWarning:%s %s" % (format(fg=YELLOW, bg=BLACK), format(reset=True), msg))
+
+def error(clazz, detail, msg):
+    _fail(clazz, detail, "%sError:%s %s" % (format(fg=RED, bg=BLACK), format(reset=True), msg))
+
+
+def verify_constants(clazz):
+    """All static final constants must be FOO_NAME style."""
+    if re.match("R\.[a-z]+", clazz.fullname): return
+
+    for f in clazz.fields:
+        if "static" in f.split and "final" in f.split:
+            if re.match("[A-Z0-9_]+", f.name) is None:
+                error(clazz, f, "Constant field names should be FOO_NAME")
+
+
+def verify_enums(clazz):
+    """Enums are bad, mmkay?"""
+    if "extends java.lang.Enum" in clazz.raw:
+        error(clazz, None, "Enums are not allowed")
+
+
+def verify_class_names(clazz):
+    """Try catching malformed class names like myMtp or MTPUser."""
+    if re.search("[A-Z]{2,}", clazz.name) is not None:
+        warn(clazz, None, "Class name style should be Mtp not MTP")
+    if re.match("[^A-Z]", clazz.name):
+        error(clazz, None, "Class must start with uppercase char")
+
+
+def verify_method_names(clazz):
+    """Try catching malformed method names, like Foo() or getMTU()."""
+    if clazz.pkg.name == "android.opengl": return
+
+    for m in clazz.methods:
+        if re.search("[A-Z]{2,}", m.name) is not None:
+            warn(clazz, m, "Method name style should be getMtu() instead of getMTU()")
+        if re.match("[^a-z]", m.name):
+            error(clazz, None, "Method name must start with lowercase char")
+
+
+def verify_callbacks(clazz):
+    """Verify Callback classes.
+    All callback classes must be abstract.
+    All methods must follow onFoo() naming style."""
+
+    if clazz.name.endswith("Callbacks"):
+        error(clazz, None, "Class must be named exactly Callback")
+    if clazz.name.endswith("Observer"):
+        warn(clazz, None, "Class should be named Callback")
+
+    if clazz.name.endswith("Callback"):
+        if "interface" in clazz.split:
+            error(clazz, None, "Callback must be abstract class")
+
+        for m in clazz.methods:
+            if not re.match("on[A-Z][a-z]*", m.name):
+                error(clazz, m, "Callback method names must be onFoo style")
+
+
+def verify_listeners(clazz):
+    """Verify Listener classes.
+    All Listener classes must be interface.
+    All methods must follow onFoo() naming style.
+    If only a single method, it must match class name:
+        interface OnFooListener { void onFoo() }"""
+
+    if clazz.name.endswith("Listener"):
+        if " abstract class " in clazz.raw:
+            error(clazz, None, "Listener should be interface")
+
+        for m in clazz.methods:
+            if not re.match("on[A-Z][a-z]*", m.name):
+                error(clazz, m, "Listener method names must be onFoo style")
+
+        if len(clazz.methods) == 1 and clazz.name.startswith("On"):
+            m = clazz.methods[0]
+            if (m.name + "Listener").lower() != clazz.name.lower():
+                error(clazz, m, "Single method name should match class name")
+
+
+def verify_actions(clazz):
+    """Verify intent actions.
+    All action names must be named ACTION_FOO.
+    All action values must be scoped by package and match name:
+        package android.foo {
+            String ACTION_BAR = "android.foo.action.BAR";
+        }"""
+    for f in clazz.fields:
+        if f.value is None: continue
+        if f.name.startswith("EXTRA_"): continue
+
+        if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
+            if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower():
+                if not f.name.startswith("ACTION_"):
+                    error(clazz, f, "Intent action must be ACTION_FOO")
+                else:
+                    if clazz.name == "Intent":
+                        prefix = "android.intent.action"
+                    elif clazz.name == "Settings":
+                        prefix = "android.settings"
+                    else:
+                        prefix = clazz.pkg.name + ".action"
+                    expected = prefix + "." + f.name[7:]
+                    if f.value != expected:
+                        error(clazz, f, "Inconsistent action value")
+
+
+def verify_extras(clazz):
+    """Verify intent extras.
+    All extra names must be named EXTRA_FOO.
+    All extra values must be scoped by package and match name:
+        package android.foo {
+            String EXTRA_BAR = "android.foo.extra.BAR";
+        }"""
+    for f in clazz.fields:
+        if f.value is None: continue
+        if f.name.startswith("ACTION_"): continue
+
+        if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
+            if "_EXTRA" in f.name or "EXTRA_" in f.name or ".extra" in f.value.lower():
+                if not f.name.startswith("EXTRA_"):
+                    error(clazz, f, "Intent extra must be EXTRA_FOO")
+                else:
+                    if clazz.name == "Intent":
+                        prefix = "android.intent.extra"
+                    else:
+                        prefix = clazz.pkg.name + ".extra"
+                    expected = prefix + "." + f.name[6:]
+                    if f.value != expected:
+                        error(clazz, f, "Inconsistent extra value")
+
+
+def verify_equals(clazz):
+    """Verify that equals() and hashCode() must be overridden together."""
+    methods = [ m.name for m in clazz.methods ]
+    eq = "equals" in methods
+    hc = "hashCode" in methods
+    if eq != hc:
+        error(clazz, None, "Must override both equals and hashCode")
+
+
+def verify_parcelable(clazz):
+    """Verify that Parcelable objects aren't hiding required bits."""
+    if "implements android.os.Parcelable" in clazz.raw:
+        creator = [ i for i in clazz.fields if i.name == "CREATOR" ]
+        write = [ i for i in clazz.methods if i.name == "writeToParcel" ]
+        describe = [ i for i in clazz.methods if i.name == "describeContents" ]
+
+        if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
+            error(clazz, None, "Parcelable requires CREATOR, writeToParcel, and describeContents")
+
+
+def verify_protected(clazz):
+    """Verify that no protected methods are allowed."""
+    for m in clazz.methods:
+        if "protected" in m.split:
+            error(clazz, m, "Protected method")
+    for f in clazz.fields:
+        if "protected" in f.split:
+            error(clazz, f, "Protected field")
+
+
+def verify_fields(clazz):
+    """Verify that all exposed fields are final.
+    Exposed fields must follow myName style.
+    Catch internal mFoo objects being exposed."""
+    for f in clazz.fields:
+        if not "final" in f.split:
+            error(clazz, f, "Bare fields must be final; consider adding accessors")
+
+        if not "static" in f.split:
+            if not re.match("[a-z]([a-zA-Z]+)?", f.name):
+                error(clazz, f, "Non-static fields must be myName")
+
+        if re.match("[m][A-Z]", f.name):
+            error(clazz, f, "Don't expose your internal objects")
+
+
+def verify_register(clazz):
+    """Verify parity of registration methods.
+    Callback objects use register/unregister methods.
+    Listener objects use add/remove methods."""
+    methods = [ m.name for m in clazz.methods ]
+    for m in clazz.methods:
+        if "Callback" in m.raw:
+            if m.name.startswith("register"):
+                other = "unregister" + m.name[8:]
+                if other not in methods:
+                    error(clazz, m, "Missing unregister")
+            if m.name.startswith("unregister"):
+                other = "register" + m.name[10:]
+                if other not in methods:
+                    error(clazz, m, "Missing register")
+
+            if m.name.startswith("add") or m.name.startswith("remove"):
+                error(clazz, m, "Callback should be register/unregister")
+
+        if "Listener" in m.raw:
+            if m.name.startswith("add"):
+                other = "remove" + m.name[3:]
+                if other not in methods:
+                    error(clazz, m, "Missing remove")
+            if m.name.startswith("remove") and not m.name.startswith("removeAll"):
+                other = "add" + m.name[6:]
+                if other not in methods:
+                    error(clazz, m, "Missing add")
+
+            if m.name.startswith("register") or m.name.startswith("unregister"):
+                error(clazz, m, "Listener should be add/remove")
+
+
+def verify_sync(clazz):
+    """Verify synchronized methods aren't exposed."""
+    for m in clazz.methods:
+        if "synchronized" in m.split:
+            error(clazz, m, "Lock exposed")
+
+
+def verify_intent_builder(clazz):
+    """Verify that Intent builders are createFooIntent() style."""
+    if clazz.name == "Intent": return
+
+    for m in clazz.methods:
+        if m.typ == "android.content.Intent":
+            if m.name.startswith("create") and m.name.endswith("Intent"):
+                pass
+            else:
+                warn(clazz, m, "Should be createFooIntent()")
+
+
+def verify_helper_classes(clazz):
+    """Verify that helper classes are named consistently with what they extend."""
+    if "extends android.app.Service" in clazz.raw:
+        if not clazz.name.endswith("Service"):
+            error(clazz, None, "Inconsistent class name")
+    if "extends android.content.ContentProvider" in clazz.raw:
+        if not clazz.name.endswith("Provider"):
+            error(clazz, None, "Inconsistent class name")
+    if "extends android.content.BroadcastReceiver" in clazz.raw:
+        if not clazz.name.endswith("Receiver"):
+            error(clazz, None, "Inconsistent class name")
+
+
+def verify_builder(clazz):
+    """Verify builder classes.
+    Methods should return the builder to enable chaining."""
+    if " extends " in clazz.raw: return
+    if not clazz.name.endswith("Builder"): return
+
+    if clazz.name != "Builder":
+        warn(clazz, None, "Should be standalone Builder class")
+
+    has_build = False
+    for m in clazz.methods:
+        if m.name == "build":
+            has_build = True
+            continue
+
+        if m.name.startswith("get"): continue
+        if m.name.startswith("clear"): continue
+
+        if not m.typ.endswith(clazz.fullname):
+            warn(clazz, m, "Should return the builder")
+
+    if not has_build:
+        warn(clazz, None, "Missing build() method")
+
+
+def verify_aidl(clazz):
+    """Catch people exposing raw AIDL."""
+    if "extends android.os.Binder" in clazz.raw or "implements android.os.IInterface" in clazz.raw:
+        error(clazz, None, "Exposing raw AIDL interface")
+
+
+def verify_internal(clazz):
+    """Catch people exposing internal classes."""
+    if clazz.pkg.name.startswith("com.android"):
+        error(clazz, None, "Exposing internal class")
+
+
+def verify_layering(clazz):
+    """Catch package layering violations.
+    For example, something in android.os depending on android.app."""
+    ranking = [
+        ["android.service","android.accessibilityservice","android.inputmethodservice","android.printservice","android.appwidget","android.webkit","android.preference","android.gesture","android.print"],
+        "android.app",
+        "android.widget",
+        "android.view",
+        "android.animation",
+        "android.provider",
+        "android.content",
+        "android.database",
+        "android.graphics",
+        "android.text",
+        "android.os",
+        "android.util"
+    ]
+
+    def rank(p):
+        for i in range(len(ranking)):
+            if isinstance(ranking[i], list):
+                for j in ranking[i]:
+                    if p.startswith(j): return i
+            else:
+                if p.startswith(ranking[i]): return i
+
+    cr = rank(clazz.pkg.name)
+    if cr is None: return
+
+    for f in clazz.fields:
+        ir = rank(f.typ)
+        if ir and ir < cr:
+            warn(clazz, f, "Field type violates package layering")
+
+    for m in clazz.methods:
+        ir = rank(m.typ)
+        if ir and ir < cr:
+            warn(clazz, m, "Method return type violates package layering")
+        for arg in m.args:
+            ir = rank(arg)
+            if ir and ir < cr:
+                warn(clazz, m, "Method argument type violates package layering")
+
+
+def verify_all(api):
+    global failures
+
+    failures = []
+    for clazz in api:
+        if clazz.pkg.name.startswith("java"): continue
+        if clazz.pkg.name.startswith("junit"): continue
+        if clazz.pkg.name.startswith("org.apache"): continue
+        if clazz.pkg.name.startswith("org.xml"): continue
+        if clazz.pkg.name.startswith("org.json"): continue
+        if clazz.pkg.name.startswith("org.w3c"): continue
+
+        verify_constants(clazz)
+        verify_enums(clazz)
+        verify_class_names(clazz)
+        verify_method_names(clazz)
+        verify_callbacks(clazz)
+        verify_listeners(clazz)
+        verify_actions(clazz)
+        verify_extras(clazz)
+        verify_equals(clazz)
+        verify_parcelable(clazz)
+        verify_protected(clazz)
+        verify_fields(clazz)
+        verify_register(clazz)
+        verify_sync(clazz)
+        verify_intent_builder(clazz)
+        verify_helper_classes(clazz)
+        verify_builder(clazz)
+        verify_aidl(clazz)
+        verify_internal(clazz)
+        verify_layering(clazz)
+
+    return failures
+
+
+cur = parse_api(sys.argv[1])
+cur_fail = verify_all(cur)
+
+if len(sys.argv) > 2:
+    prev = parse_api(sys.argv[2])
+    prev_fail = verify_all(prev)
+
+    # ignore errors from previous API level
+    for p in prev_fail:
+        if p in cur_fail:
+            cur_fail.remove(p)
+
+
+for f in cur_fail:
+    print f
+    print
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index a280348..e80a8f4 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -354,6 +354,7 @@
                 sr.autoJoinStatus = in.readInt();
                 sr.untrusted = in.readInt() != 0;
                 sr.numConnection = in.readInt();
+                sr.numUsage = in.readInt();
                 int n = in.readInt();
                 if (n != 0) {
                     sr.informationElements = new InformationElement[n];