Merge "Change display Strings to CharSequence (1/3)" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 79d13d9..7dfa6a0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -322,15 +322,17 @@
 	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 \
 	media/java/android/media/routing/IMediaRouteService.aidl \
 	media/java/android/media/routing/IMediaRouteClientCallback.aidl \
 	media/java/android/media/routing/IMediaRouter.aidl \
 	media/java/android/media/routing/IMediaRouterDelegate.aidl \
 	media/java/android/media/routing/IMediaRouterRoutingCallback.aidl \
 	media/java/android/media/routing/IMediaRouterStateCallback.aidl \
-	media/java/android/media/projection/IMediaProjection.aidl \
-	media/java/android/media/projection/IMediaProjectionCallback.aidl \
-	media/java/android/media/projection/IMediaProjectionManager.aidl \
 	media/java/android/media/session/IActiveSessionsListener.aidl \
 	media/java/android/media/session/ISessionController.aidl \
 	media/java/android/media/session/ISessionControllerCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index 966d1fb..3b4edcd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -746,6 +746,7 @@
     field public static final int l_resource_pad23 = 16843770; // 0x10103fa
     field public static final int l_resource_pad24 = 16843769; // 0x10103f9
     field public static final int l_resource_pad25 = 16843768; // 0x10103f8
+    field public static final int l_resource_pad26 = 16843767; // 0x10103f7
     field public static final int l_resource_pad3 = 16843790; // 0x101040e
     field public static final int l_resource_pad4 = 16843789; // 0x101040d
     field public static final int l_resource_pad5 = 16843788; // 0x101040c
@@ -947,6 +948,7 @@
     field public static final int popupKeyboard = 16843331; // 0x1010243
     field public static final int popupLayout = 16843323; // 0x101023b
     field public static final int popupMenuStyle = 16843520; // 0x1010300
+    field public static final int popupTheme = 16843951; // 0x10104af
     field public static final int popupWindowStyle = 16842870; // 0x1010076
     field public static final int port = 16842793; // 0x1010029
     field public static final int positiveButtonText = 16843253; // 0x10101f5
@@ -1306,6 +1308,7 @@
     field public static final int toXScale = 16843203; // 0x10101c3
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
+    field public static final int toolbarStyle = 16843952; // 0x10104b0
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -1329,7 +1332,6 @@
     field public static final int trimPathEnd = 16843813; // 0x1010425
     field public static final int trimPathOffset = 16843814; // 0x1010426
     field public static final int trimPathStart = 16843812; // 0x1010424
-    field public static final int tvInputType = 16843767; // 0x10103f7
     field public static final int type = 16843169; // 0x10101a1
     field public static final int typeface = 16842902; // 0x1010096
     field public static final int uiOptions = 16843672; // 0x1010398
@@ -2744,6 +2746,7 @@
     method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
     method public java.lang.String getPassword(android.accounts.Account);
+    method public java.lang.String getPreviousName(android.accounts.Account);
     method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -2751,6 +2754,7 @@
     method public java.lang.String peekAuthToken(android.accounts.Account, java.lang.String);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
+    method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
     method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
     method public void setPassword(android.accounts.Account, java.lang.String);
     method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -3820,6 +3824,7 @@
     method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener);
     method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener);
     field public static final int MODE_ALLOWED = 0; // 0x0
+    field public static final int MODE_DEFAULT = 3; // 0x3
     field public static final int MODE_ERRORED = 2; // 0x2
     field public static final int MODE_IGNORED = 1; // 0x1
     field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -4583,6 +4588,7 @@
     field public static final int DEFAULT_SOUND = 1; // 0x1
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
+    field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
     field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
@@ -8877,6 +8883,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int FLAG_COSTS_MONEY = 1; // 0x1
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
+    field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
     field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
     field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
@@ -15011,6 +15018,7 @@
     field public static final java.lang.String KEY_REFERENCE_CLOCK_ID = "reference-clock-id";
     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";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -16154,6 +16162,85 @@
 
 }
 
+package android.media.browse {
+
+  public final class MediaBrowser {
+    ctor public MediaBrowser(android.content.Context, android.content.ComponentName, android.media.browse.MediaBrowser.ConnectionCallback, android.os.Bundle);
+    method public void connect();
+    method public void disconnect();
+    method public android.os.Bundle getExtras();
+    method public android.net.Uri getRoot();
+    method public android.media.session.MediaSession.Token getSessionToken();
+    method public boolean isConnected();
+    method public void loadThumbnail(android.net.Uri, int, int, android.media.browse.MediaBrowser.ThumbnailCallback);
+    method public void subscribe(android.net.Uri, android.media.browse.MediaBrowser.SubscriptionCallback);
+    method public void unsubscribe(android.net.Uri);
+  }
+
+  public static class MediaBrowser.ConnectionCallback {
+    ctor public MediaBrowser.ConnectionCallback();
+    method public void onConnected();
+    method public void onConnectionFailed();
+    method public void onConnectionSuspended();
+  }
+
+  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 static abstract class MediaBrowser.ThumbnailCallback {
+    ctor public MediaBrowser.ThumbnailCallback();
+    method public void onError(android.net.Uri);
+    method public void onThumbnailLoaded(android.net.Uri, android.graphics.Bitmap);
+  }
+
+  public final class MediaBrowserItem implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getExtras();
+    method public int getFlags();
+    method public int getIconResId();
+    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 boolean isBrowsable();
+    method public boolean isPlayable();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_BROWSABLE = 1; // 0x1
+    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 setIconResId(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 protected abstract android.media.browse.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
+    method protected abstract android.graphics.Bitmap onGetThumbnail(android.net.Uri, int, int);
+    method protected abstract java.util.List<android.media.browse.MediaBrowserItem> onLoadChildren(android.net.Uri);
+    method public void setSessionToken(android.media.session.MediaSession.Token);
+    field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+  }
+
+  public static class MediaBrowserService.BrowserRoot {
+    ctor public MediaBrowserService.BrowserRoot(android.net.Uri, android.os.Bundle);
+  }
+
+}
+
 package android.media.effect {
 
   public abstract class Effect {
@@ -16689,33 +16776,33 @@
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final int SERVICE_TYPE_AUDIO = 2; // 0x2
-    field public static final int SERVICE_TYPE_AUDIO_VIDEO = 1; // 0x1
-    field public static final int SERVICE_TYPE_OTHER = 0; // 0x0
-    field public static final int TYPE_1SEG = 197632; // 0x30400
-    field public static final int TYPE_ATSC_C = 131584; // 0x20200
-    field public static final int TYPE_ATSC_M_H = 131840; // 0x20300
-    field public static final int TYPE_ATSC_T = 131072; // 0x20000
-    field public static final int TYPE_CMMB = 262400; // 0x40100
-    field public static final int TYPE_DTMB = 262144; // 0x40000
-    field public static final int TYPE_DVB_C = 66048; // 0x10200
-    field public static final int TYPE_DVB_C2 = 66049; // 0x10201
-    field public static final int TYPE_DVB_H = 66304; // 0x10300
-    field public static final int TYPE_DVB_S = 65792; // 0x10100
-    field public static final int TYPE_DVB_S2 = 65793; // 0x10101
-    field public static final int TYPE_DVB_SH = 66560; // 0x10400
-    field public static final int TYPE_DVB_T = 65536; // 0x10000
-    field public static final int TYPE_DVB_T2 = 65537; // 0x10001
-    field public static final int TYPE_ISDB_C = 197376; // 0x30300
-    field public static final int TYPE_ISDB_S = 197120; // 0x30200
-    field public static final int TYPE_ISDB_T = 196608; // 0x30000
-    field public static final int TYPE_ISDB_TB = 196864; // 0x30100
-    field public static final int TYPE_NTSC = 1; // 0x1
-    field public static final int TYPE_OTHER = 0; // 0x0
-    field public static final int TYPE_PAL = 2; // 0x2
-    field public static final int TYPE_SECAM = 3; // 0x3
-    field public static final int TYPE_S_DMB = 327936; // 0x50100
-    field public static final int TYPE_T_DMB = 327680; // 0x50000
+    field public static final java.lang.String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
+    field public static final java.lang.String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO";
+    field public static final java.lang.String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER";
+    field public static final java.lang.String TYPE_1SEG = "TYPE_1SEG";
+    field public static final java.lang.String TYPE_ATSC_C = "TYPE_ATSC_C";
+    field public static final java.lang.String TYPE_ATSC_M_H = "TYPE_ATSC_M_H";
+    field public static final java.lang.String TYPE_ATSC_T = "TYPE_ATSC_T";
+    field public static final java.lang.String TYPE_CMMB = "TYPE_CMMB";
+    field public static final java.lang.String TYPE_DTMB = "TYPE_DTMB";
+    field public static final java.lang.String TYPE_DVB_C = "TYPE_DVB_C";
+    field public static final java.lang.String TYPE_DVB_C2 = "TYPE_DVB_C2";
+    field public static final java.lang.String TYPE_DVB_H = "TYPE_DVB_H";
+    field public static final java.lang.String TYPE_DVB_S = "TYPE_DVB_S";
+    field public static final java.lang.String TYPE_DVB_S2 = "TYPE_DVB_S2";
+    field public static final java.lang.String TYPE_DVB_SH = "TYPE_DVB_SH";
+    field public static final java.lang.String TYPE_DVB_T = "TYPE_DVB_T";
+    field public static final java.lang.String TYPE_DVB_T2 = "TYPE_DVB_T2";
+    field public static final java.lang.String TYPE_ISDB_C = "TYPE_ISDB_C";
+    field public static final java.lang.String TYPE_ISDB_S = "TYPE_ISDB_S";
+    field public static final java.lang.String TYPE_ISDB_T = "TYPE_ISDB_T";
+    field public static final java.lang.String TYPE_ISDB_TB = "TYPE_ISDB_TB";
+    field public static final java.lang.String TYPE_NTSC = "TYPE_NTSC";
+    field public static final java.lang.String TYPE_OTHER = "TYPE_OTHER";
+    field public static final java.lang.String TYPE_PAL = "TYPE_PAL";
+    field public static final java.lang.String TYPE_SECAM = "TYPE_SECAM";
+    field public static final java.lang.String TYPE_S_DMB = "TYPE_S_DMB";
+    field public static final java.lang.String TYPE_T_DMB = "TYPE_T_DMB";
     field public static final java.lang.String VIDEO_FORMAT_1080I = "VIDEO_FORMAT_1080I";
     field public static final java.lang.String VIDEO_FORMAT_1080P = "VIDEO_FORMAT_1080P";
     field public static final java.lang.String VIDEO_FORMAT_2160P = "VIDEO_FORMAT_2160P";
@@ -16745,9 +16832,12 @@
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
     field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
     field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
     field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
     field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -16789,17 +16879,16 @@
     method public java.lang.CharSequence loadLabel(android.content.Context);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final java.lang.String EXTRA_INPUT_ID = "inputId";
-    field public static final int TYPE_COMPONENT = 6; // 0x6
-    field public static final int TYPE_COMPOSITE = 3; // 0x3
-    field public static final int TYPE_DISPLAY_PORT = 10; // 0xa
-    field public static final int TYPE_DVI = 8; // 0x8
-    field public static final int TYPE_HDMI = 9; // 0x9
-    field public static final int TYPE_OTHER_HARDWARE = 1; // 0x1
-    field public static final int TYPE_SCART = 5; // 0x5
-    field public static final int TYPE_SVIDEO = 4; // 0x4
-    field public static final int TYPE_TUNER = 2; // 0x2
-    field public static final int TYPE_VGA = 7; // 0x7
-    field public static final int TYPE_VIRTUAL = 0; // 0x0
+    field public static final int TYPE_COMPONENT = 1004; // 0x3ec
+    field public static final int TYPE_COMPOSITE = 1001; // 0x3e9
+    field public static final int TYPE_DISPLAY_PORT = 1008; // 0x3f0
+    field public static final int TYPE_DVI = 1006; // 0x3ee
+    field public static final int TYPE_HDMI = 1007; // 0x3ef
+    field public static final int TYPE_OTHER = 1000; // 0x3e8
+    field public static final int TYPE_SCART = 1003; // 0x3eb
+    field public static final int TYPE_SVIDEO = 1002; // 0x3ea
+    field public static final int TYPE_TUNER = 0; // 0x0
+    field public static final int TYPE_VGA = 1005; // 0x3ed
   }
 
   public final class TvInputManager {
@@ -17374,18 +17463,6 @@
     method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
   }
 
-  public abstract interface PSKKeyManager {
-    method public abstract java.lang.String chooseClientKeyIdentity(java.lang.String, java.net.Socket);
-    method public abstract java.lang.String chooseClientKeyIdentity(java.lang.String, javax.net.ssl.SSLEngine);
-    method public abstract java.lang.String chooseServerKeyIdentityHint(java.net.Socket);
-    method public abstract java.lang.String chooseServerKeyIdentityHint(javax.net.ssl.SSLEngine);
-    method public abstract javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, java.net.Socket);
-    method public abstract javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, javax.net.ssl.SSLEngine);
-    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
-    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
-  }
-
   public class ParseException extends java.lang.RuntimeException {
     field public java.lang.String response;
   }
@@ -17412,6 +17489,19 @@
     method public void writeToParcel(android.os.Parcel, int);
   }
 
+  public abstract class PskKeyManager {
+    ctor public PskKeyManager();
+    method public java.lang.String chooseClientKeyIdentity(java.lang.String, java.net.Socket);
+    method public java.lang.String chooseClientKeyIdentity(java.lang.String, javax.net.ssl.SSLEngine);
+    method public java.lang.String chooseServerKeyIdentityHint(java.net.Socket);
+    method public java.lang.String chooseServerKeyIdentityHint(javax.net.ssl.SSLEngine);
+    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, java.net.Socket);
+    method public javax.crypto.SecretKey getKey(java.lang.String, java.lang.String, javax.net.ssl.SSLEngine);
+    field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80
+    field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
+  }
+
   public final class RouteInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.IpPrefix getDestination();
@@ -27151,14 +27241,19 @@
     method public final void cancelNotification(java.lang.String);
     method public final void cancelNotifications(java.lang.String[]);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+    method public final int getCurrentListenerFlags();
     method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onListenerConnected();
+    method public void onListenerFlagsChanged(int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     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 requestListenerFlags(int);
+    field public static final int FLAG_DISABLE_HOST_ALERTS = 1; // 0x1
+    field public static final int FLAG_NONE = 0; // 0x0
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
   }
 
@@ -27239,15 +27334,10 @@
 package android.service.voice {
 
   public class AlwaysOnHotwordDetector {
-    method public int getAvailability();
     method public android.content.Intent getManageIntent(int);
     method public int getSupportedRecognitionModes();
     method public int startRecognition(int);
     method public int stopRecognition();
-    field public static final int KEYPHRASE_ENROLLED = 2; // 0x2
-    field public static final int KEYPHRASE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
-    field public static final int KEYPHRASE_UNENROLLED = 1; // 0x1
-    field public static final int KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
     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
@@ -27255,21 +27345,28 @@
     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
+    field public static final int STATE_INVALID = -3; // 0xfffffffd
+    field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
+    field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
+    field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
     field public static final int STATUS_ERROR = -2147483648; // 0x80000000
     field public static final int STATUS_OK = 0; // 0x0
   }
 
   public static abstract interface AlwaysOnHotwordDetector.Callback {
+    method public abstract void onAvailabilityChanged(int);
     method public abstract void onDetected(byte[]);
     method public abstract void onDetectionStopped();
   }
 
   public class VoiceInteractionService extends android.app.Service {
     ctor public VoiceInteractionService();
-    method public final android.service.voice.AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback);
+    method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback);
     method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onReady();
+    method public void onShutdown();
     method public void startSession(android.os.Bundle);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
     field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
@@ -28620,14 +28717,13 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public class RemoteCallVideoClient implements android.os.IBinder.DeathRecipient {
-    method public void binderDied();
-    method public void handleCallSessionEvent(int) throws android.os.RemoteException;
-    method public void handleCameraCapabilitiesChange(android.telecomm.CallCameraCapabilities) throws android.os.RemoteException;
-    method public void receiveSessionModifyRequest(android.telecomm.VideoCallProfile) throws android.os.RemoteException;
-    method public void receiveSessionModifyResponse(int, android.telecomm.VideoCallProfile, android.telecomm.VideoCallProfile) throws android.os.RemoteException;
-    method public void updateCallDataUsage(int) throws android.os.RemoteException;
-    method public void updatePeerDimensions(int, int) throws android.os.RemoteException;
+  public class RemoteCallVideoClient {
+    method public void handleCallSessionEvent(int);
+    method public void handleCameraCapabilitiesChange(android.telecomm.CallCameraCapabilities);
+    method public void receiveSessionModifyRequest(android.telecomm.VideoCallProfile);
+    method public void receiveSessionModifyResponse(int, android.telecomm.VideoCallProfile, android.telecomm.VideoCallProfile);
+    method public void updateCallDataUsage(int);
+    method public void updatePeerDimensions(int, int);
   }
 
   public class RemoteCallVideoProvider {
@@ -31892,8 +31988,8 @@
     method public android.animation.Animator onDisappear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int);
     method public android.animation.Animator onDisappear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues);
     method public void setMode(int);
-    field public static final int IN = 1; // 0x1
-    field public static final int OUT = 2; // 0x2
+    field public static final int MODE_IN = 1; // 0x1
+    field public static final int MODE_OUT = 2; // 0x2
   }
 
   public abstract class VisibilityPropagation extends android.transition.TransitionPropagation {
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index aab6e80..09b484b 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -663,6 +663,72 @@
     }
 
     /**
+     * Rename the specified {@link Account}.  This is equivalent to removing
+     * the existing account and adding a new renamed account with the old
+     * account's user data.
+     *
+     * <p>It is safe to call this method from the main thread.
+     *
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
+     * and have the same UID as the account's authenticator.
+     *
+     * @param account The {@link Account} to rename
+     * @param newName String name to be associated with the account.
+     * @param callback Callback to invoke when the request completes, null for
+     *     no callback
+     * @param handler {@link Handler} identifying the callback thread, null for
+     *     the main thread
+     * @return An {@link AccountManagerFuture} which resolves to the Account
+     *     after the name change. If successful the account's name will be the
+     *     specified new name.
+     */
+    public AccountManagerFuture<Account> renameAccount(
+            final Account account,
+            final String newName,
+            AccountManagerCallback<Account> callback,
+            Handler handler) {
+        if (account == null) throw new IllegalArgumentException("account is null.");
+        if (TextUtils.isEmpty(newName)) {
+              throw new IllegalArgumentException("newName is empty or null.");
+        }
+        return new Future2Task<Account>(handler, callback) {
+            @Override
+            public void doWork() throws RemoteException {
+                mService.renameAccount(mResponse, account, newName);
+            }
+            @Override
+            public Account bundleToResult(Bundle bundle) throws AuthenticatorException {
+                String name = bundle.getString(KEY_ACCOUNT_NAME);
+                String type = bundle.getString(KEY_ACCOUNT_TYPE);
+                return new Account(name, type);
+            }
+        }.start();
+    }
+
+    /**
+     * Gets the previous name associated with the account or {@code null}, if
+     * none. This is intended so that clients of {@link
+     * #LOGIN_ACCOUNTS_CHANGED_ACTION} broadcasts can determine if an
+     * authenticator has renamed an account.
+     *
+     * <p>It is safe to call this method from the main thread.
+     *
+     * @param account The account to query for a previous name.
+     * @return The account's previous name, null if the account has never been
+     *         renamed.
+     */
+    public String getPreviousName(final Account account) {
+        if (account == null) throw new IllegalArgumentException("account is null");
+        try {
+            return mService.getPreviousName(account);
+        } catch (RemoteException e) {
+            // will never happen
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
      * Removes an account from the AccountManager.  Does nothing if the account
      * does not exist.  Does not delete the account from the server.
      * The authenticator may have its own policies preventing account
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index a04875d..a133788 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -69,4 +69,10 @@
     boolean addSharedAccountAsUser(in Account account, int userId);
     Account[] getSharedAccountsAsUser(int userId);
     boolean removeSharedAccountAsUser(in Account account, int userId);
+
+    /* Account renaming. */
+    void renameAccount(in IAccountManagerResponse response, in Account accountToRename, String newName);
+    String getPreviousName(in Account account);
+    boolean renameSharedAccountAsUser(in Account accountToRename, String newName, int userId);
+
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index fb70098..342155d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -284,6 +284,17 @@
             return true;
         }
 
+        case START_ACTIVITY_FROM_RECENTS_TRANSACTION:
+        {
+            data.enforceInterface(IActivityManager.descriptor);
+            int taskId = data.readInt();
+            Bundle options = data.readInt() == 0 ? null : Bundle.CREATOR.createFromParcel(data);
+            int result = startActivityFromRecents(taskId, options);
+            reply.writeNoException();
+            reply.writeInt(result);
+            return true;
+        }
+
         case FINISH_ACTIVITY_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -2482,6 +2493,24 @@
         data.recycle();
         return result != 0;
     }
+    public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(taskId);
+        if (options == null) {
+            data.writeInt(0);
+        } else {
+            data.writeInt(1);
+            options.writeToParcel(data, 0);
+        }
+        mRemote.transact(START_ACTIVITY_FROM_RECENTS_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int result = reply.readInt();
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
     public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 990ea85..caadecb 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -94,6 +94,13 @@
      */
     public static final int MODE_ERRORED = 2;
 
+    /**
+     * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should
+     * use its default security check.  This mode is not normally used; it should only be used
+     * with appop permissions, and callers must explicitly check for it and deal with it.
+     */
+    public static final int MODE_DEFAULT = 3;
+
     // when adding one of these:
     //  - increment _NUM_OP
     //  - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
@@ -588,7 +595,7 @@
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_IGNORED, // OP_GET_USAGE_STATS
+            AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4d6bd4b..175b6a5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -413,8 +413,7 @@
         registerService(CONNECTIVITY_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
-                    return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b),
-                        ctx.getPackageName());
+                    return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));
                 }});
 
         registerService(COUNTRY_DETECTOR, new StaticServiceFetcher() {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ac29161..cc13a3b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -86,6 +86,7 @@
             ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
     public boolean startNextMatchingActivity(IBinder callingActivity,
             Intent intent, Bundle options) throws RemoteException;
+    public int startActivityFromRecents(int taskId, Bundle options) throws RemoteException;
     public boolean finishActivity(IBinder token, int code, Intent data, boolean finishTask)
             throws RemoteException;
     public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
@@ -756,4 +757,5 @@
     int IS_BG_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
     int MEDIA_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
     int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
+    int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229;
 }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 5b92538..113c533 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -59,6 +59,8 @@
     void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
 
     ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token);
+    void requestFlagsFromListener(in INotificationListener token, int flags);
+    int getFlagsFromListener(in INotificationListener token);
 
     ZenModeConfig getZenModeConfig();
     boolean setZenModeConfig(in ZenModeConfig config);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index da59a03..5782edc 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -799,6 +799,12 @@
     public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";
 
     /**
+     * {@link #extras} key: the indices of actions to be shown in the compact view,
+     * as supplied to (e.g.) {@link MediaStyle#setShowActionsInCompactView(int...)}.
+     */
+    public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
+
+    /**
      * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
      * displayed in the heads up space.
      *
@@ -3362,6 +3368,9 @@
             if (mToken != null) {
                 extras.putParcelable(EXTRA_MEDIA_SESSION, mToken);
             }
+            if (mActionsToShowInCompact != null) {
+                extras.putIntArray(EXTRA_COMPACT_ACTIONS, mActionsToShowInCompact);
+            }
         }
 
         private RemoteViews generateMediaActionButton(Action action) {
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index de3b881..87d14b9 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2153,8 +2153,16 @@
      * @param sync the master auto-sync setting that applies to all the providers and accounts
      */
     public static void setMasterSyncAutomatically(boolean sync) {
+        setMasterSyncAutomaticallyAsUser(sync, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * @see #setMasterSyncAutomatically(boolean)
+     * @hide
+     */
+    public static void setMasterSyncAutomaticallyAsUser(boolean sync, int userId) {
         try {
-            getContentService().setMasterSyncAutomatically(sync);
+            getContentService().setMasterSyncAutomaticallyAsUser(sync, userId);
         } catch (RemoteException e) {
             // exception ignored; if this is thrown then it means the runtime is in the midst of
             // being restarted
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index d363ad1..9998f08 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -128,6 +128,7 @@
     void setIsSyncable(in Account account, String providerName, int syncable);
 
     void setMasterSyncAutomatically(boolean flag);
+    void setMasterSyncAutomaticallyAsUser(boolean flag, int userId);
 
     boolean getMasterSyncAutomatically();
     boolean getMasterSyncAutomaticallyAsUser(int userId);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 5e55ba7..4b339a1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -110,6 +110,8 @@
 
     int getFlagsForUid(int uid);
 
+    String[] getAppOpPermissionPackages(String permissionName);
+
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
     boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 5a63e5f..af574db 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -69,6 +69,13 @@
     public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;
 
     /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>development</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     */
+    public static final int PROTECTION_FLAG_APPOP = 0x40;
+
+    /**
      * Mask for {@link #protectionLevel}: the basic protection type.
      */
     public static final int PROTECTION_MASK_BASE = 0xf;
@@ -153,6 +160,9 @@
         if ((level&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
             protLevel += "|development";
         }
+        if ((level&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
+            protLevel += "|appop";
+        }
         return protLevel;
     }
 
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 38ddede..5face69 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1824,15 +1824,7 @@
             remainder = languageTag.substring(separator);
         }
 
-        if ("id".equals(language)) {
-            return "in" + remainder;
-        } else if ("yi".equals(language)) {
-            return "ji" + remainder;
-        } else if ("he".equals(language)) {
-            return "iw" + remainder;
-        } else {
-            return languageTag;
-        }
+        return Locale.adjustLanguageCode(language) + remainder;
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a88e659..f18cb7d 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -16,8 +16,9 @@
 
 package android.hardware.camera2;
 
-import android.hardware.camera2.CaptureResult.Key;
 import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.impl.PublicKey;
+import android.hardware.camera2.impl.SyntheticKey;
 import android.hardware.camera2.utils.TypeReference;
 import android.util.Rational;
 
@@ -321,6 +322,7 @@
      * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      */
+    @PublicKey
     public static final Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES =
             new Key<int[]>("android.colorCorrection.availableAberrationCorrectionModes", int[].class);
 
@@ -332,6 +334,7 @@
      * valid anti-banding modes that the application may request
      * for this camera device; they must include AUTO.</p>
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AE_AVAILABLE_ANTIBANDING_MODES =
             new Key<int[]>("android.control.aeAvailableAntibandingModes", int[].class);
 
@@ -351,6 +354,7 @@
      *
      * @see CaptureRequest#CONTROL_AE_MODE
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AE_AVAILABLE_MODES =
             new Key<int[]>("android.control.aeAvailableModes", int[].class);
 
@@ -358,6 +362,7 @@
      * <p>List of frame rate ranges supported by the
      * auto-exposure (AE) algorithm/hardware</p>
      */
+    @PublicKey
     public static final Key<android.util.Range<Integer>[]> CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES =
             new Key<android.util.Range<Integer>[]>("android.control.aeAvailableTargetFpsRanges", new TypeReference<android.util.Range<Integer>[]>() {{ }});
 
@@ -368,6 +373,7 @@
      *
      * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP
      */
+    @PublicKey
     public static final Key<android.util.Range<Integer>> CONTROL_AE_COMPENSATION_RANGE =
             new Key<android.util.Range<Integer>>("android.control.aeCompensationRange", new TypeReference<android.util.Range<Integer>>() {{ }});
 
@@ -375,6 +381,7 @@
      * <p>Smallest step by which exposure compensation
      * can be changed</p>
      */
+    @PublicKey
     public static final Key<Rational> CONTROL_AE_COMPENSATION_STEP =
             new Key<Rational>("android.control.aeCompensationStep", Rational.class);
 
@@ -391,6 +398,7 @@
      * @see CaptureRequest#CONTROL_AF_MODE
      * @see CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AF_AVAILABLE_MODES =
             new Key<int[]>("android.control.afAvailableModes", int[].class);
 
@@ -410,6 +418,7 @@
      * @see CaptureRequest#CONTROL_EFFECT_MODE
      * @see CaptureRequest#CONTROL_MODE
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AVAILABLE_EFFECTS =
             new Key<int[]>("android.control.availableEffects", int[].class);
 
@@ -424,6 +433,7 @@
      *
      * @see CaptureRequest#CONTROL_SCENE_MODE
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AVAILABLE_SCENE_MODES =
             new Key<int[]>("android.control.availableSceneModes", int[].class);
 
@@ -431,6 +441,7 @@
      * <p>List of video stabilization modes that can
      * be supported</p>
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES =
             new Key<int[]>("android.control.availableVideoStabilizationModes", int[].class);
 
@@ -450,6 +461,7 @@
      * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
      * @see CaptureRequest#CONTROL_AWB_MODE
      */
+    @PublicKey
     public static final Key<int[]> CONTROL_AWB_AVAILABLE_MODES =
             new Key<int[]>("android.control.awbAvailableModes", int[].class);
 
@@ -476,6 +488,8 @@
      *
      * @see CaptureRequest#CONTROL_AE_REGIONS
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<Integer> CONTROL_MAX_REGIONS_AE =
             new Key<Integer>("android.control.maxRegionsAe", int.class);
 
@@ -487,6 +501,8 @@
      *
      * @see CaptureRequest#CONTROL_AWB_REGIONS
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<Integer> CONTROL_MAX_REGIONS_AWB =
             new Key<Integer>("android.control.maxRegionsAwb", int.class);
 
@@ -498,6 +514,8 @@
      *
      * @see CaptureRequest#CONTROL_AF_REGIONS
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<Integer> CONTROL_MAX_REGIONS_AF =
             new Key<Integer>("android.control.maxRegionsAf", int.class);
 
@@ -538,6 +556,7 @@
      *
      * @see CaptureRequest#EDGE_MODE
      */
+    @PublicKey
     public static final Key<int[]> EDGE_AVAILABLE_EDGE_MODES =
             new Key<int[]>("android.edge.availableEdgeModes", int[].class);
 
@@ -547,6 +566,7 @@
      * <p>If no flash, none of the flash controls do
      * anything. All other metadata should return 0.</p>
      */
+    @PublicKey
     public static final Key<Boolean> FLASH_INFO_AVAILABLE =
             new Key<Boolean>("android.flash.info.available", boolean.class);
 
@@ -558,6 +578,7 @@
      *
      * @see CaptureRequest#HOT_PIXEL_MODE
      */
+    @PublicKey
     public static final Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES =
             new Key<int[]>("android.hotPixel.availableHotPixelModes", int[].class);
 
@@ -577,6 +598,7 @@
      * <li>All non (0, 0) sizes will have non-zero widths and heights.</li>
      * </ul>
      */
+    @PublicKey
     public static final Key<android.util.Size[]> JPEG_AVAILABLE_THUMBNAIL_SIZES =
             new Key<android.util.Size[]>("android.jpeg.availableThumbnailSizes", android.util.Size[].class);
 
@@ -588,6 +610,7 @@
      * <p>If the camera device supports variable apertures, the aperture value
      * in this list will be sorted in ascending order.</p>
      */
+    @PublicKey
     public static final Key<float[]> LENS_INFO_AVAILABLE_APERTURES =
             new Key<float[]>("android.lens.info.availableApertures", float[].class);
 
@@ -601,6 +624,7 @@
      *
      * @see CaptureRequest#LENS_FILTER_DENSITY
      */
+    @PublicKey
     public static final Key<float[]> LENS_INFO_AVAILABLE_FILTER_DENSITIES =
             new Key<float[]>("android.lens.info.availableFilterDensities", float[].class);
 
@@ -614,6 +638,7 @@
      *
      * @see CaptureRequest#LENS_FOCAL_LENGTH
      */
+    @PublicKey
     public static final Key<float[]> LENS_INFO_AVAILABLE_FOCAL_LENGTHS =
             new Key<float[]>("android.lens.info.availableFocalLengths", float[].class);
 
@@ -626,6 +651,7 @@
      *
      * @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
      */
+    @PublicKey
     public static final Key<int[]> LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION =
             new Key<int[]>("android.lens.info.availableOpticalStabilization", int[].class);
 
@@ -637,6 +663,7 @@
      *
      * @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
      */
+    @PublicKey
     public static final Key<Float> LENS_INFO_HYPERFOCAL_DISTANCE =
             new Key<Float>("android.lens.info.hyperfocalDistance", float.class);
 
@@ -647,6 +674,7 @@
      * 0.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
+    @PublicKey
     public static final Key<Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE =
             new Key<Float>("android.lens.info.minimumFocusDistance", float.class);
 
@@ -674,6 +702,7 @@
      * @see #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE
      * @see #LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED
      */
+    @PublicKey
     public static final Key<Integer> LENS_INFO_FOCUS_DISTANCE_CALIBRATION =
             new Key<Integer>("android.lens.info.focusDistanceCalibration", int.class);
 
@@ -683,6 +712,7 @@
      * @see #LENS_FACING_FRONT
      * @see #LENS_FACING_BACK
      */
+    @PublicKey
     public static final Key<Integer> LENS_FACING =
             new Key<Integer>("android.lens.facing", int.class);
 
@@ -693,6 +723,7 @@
      *
      * @see CaptureRequest#NOISE_REDUCTION_MODE
      */
+    @PublicKey
     public static final Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES =
             new Key<int[]>("android.noiseReduction.availableNoiseReductionModes", int[].class);
 
@@ -758,6 +789,8 @@
      *
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<Integer> REQUEST_MAX_NUM_OUTPUT_RAW =
             new Key<Integer>("android.request.maxNumOutputRaw", int.class);
 
@@ -784,6 +817,8 @@
      *
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<Integer> REQUEST_MAX_NUM_OUTPUT_PROC =
             new Key<Integer>("android.request.maxNumOutputProc", int.class);
 
@@ -804,6 +839,8 @@
      *
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING =
             new Key<Integer>("android.request.maxNumOutputProcStalling", int.class);
 
@@ -842,6 +879,7 @@
      *
      * @see CaptureResult#REQUEST_PIPELINE_DEPTH
      */
+    @PublicKey
     public static final Key<Byte> REQUEST_PIPELINE_MAX_DEPTH =
             new Key<Byte>("android.request.pipelineMaxDepth", byte.class);
 
@@ -862,6 +900,7 @@
      * partial results.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
+    @PublicKey
     public static final Key<Integer> REQUEST_PARTIAL_RESULT_COUNT =
             new Key<Integer>("android.request.partialResultCount", int.class);
 
@@ -892,6 +931,7 @@
      * @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
      * @see #REQUEST_AVAILABLE_CAPABILITIES_RAW
      */
+    @PublicKey
     public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
             new Key<int[]>("android.request.availableCapabilities", int[].class);
 
@@ -1001,6 +1041,7 @@
      * than this ratio allows will be rounded up to the minimum
      * allowed size by the camera device.</p>
      */
+    @PublicKey
     public static final Key<Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM =
             new Key<Float>("android.scaler.availableMaxDigitalZoom", float.class);
 
@@ -1360,6 +1401,8 @@
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<android.hardware.camera2.params.StreamConfigurationMap> SCALER_STREAM_CONFIGURATION_MAP =
             new Key<android.hardware.camera2.params.StreamConfigurationMap>("android.scaler.streamConfigurationMap", android.hardware.camera2.params.StreamConfigurationMap.class);
 
@@ -1382,6 +1425,7 @@
      * @see #SCALER_CROPPING_TYPE_CENTER_ONLY
      * @see #SCALER_CROPPING_TYPE_FREEFORM
      */
+    @PublicKey
     public static final Key<Integer> SCALER_CROPPING_TYPE =
             new Key<Integer>("android.scaler.croppingType", int.class);
 
@@ -1391,6 +1435,7 @@
      * <p>It is smaller or equal to
      * sensor full pixel array, which could include the black calibration pixels.</p>
      */
+    @PublicKey
     public static final Key<android.graphics.Rect> SENSOR_INFO_ACTIVE_ARRAY_SIZE =
             new Key<android.graphics.Rect>("android.sensor.info.activeArraySize", android.graphics.Rect.class);
 
@@ -1403,6 +1448,7 @@
      *
      * @see CaptureRequest#SENSOR_SENSITIVITY
      */
+    @PublicKey
     public static final Key<android.util.Range<Integer>> SENSOR_INFO_SENSITIVITY_RANGE =
             new Key<android.util.Range<Integer>>("android.sensor.info.sensitivityRange", new TypeReference<android.util.Range<Integer>>() {{ }});
 
@@ -1416,6 +1462,7 @@
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT =
             new Key<Integer>("android.sensor.info.colorFilterArrangement", int.class);
 
@@ -1429,6 +1476,7 @@
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      */
+    @PublicKey
     public static final Key<android.util.Range<Long>> SENSOR_INFO_EXPOSURE_TIME_RANGE =
             new Key<android.util.Range<Long>>("android.sensor.info.exposureTimeRange", new TypeReference<android.util.Range<Long>>() {{ }});
 
@@ -1449,6 +1497,7 @@
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#SENSOR_FRAME_DURATION
      */
+    @PublicKey
     public static final Key<Long> SENSOR_INFO_MAX_FRAME_DURATION =
             new Key<Long>("android.sensor.info.maxFrameDuration", long.class);
 
@@ -1460,6 +1509,7 @@
      *
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.util.SizeF> SENSOR_INFO_PHYSICAL_SIZE =
             new Key<android.util.SizeF>("android.sensor.info.physicalSize", android.util.SizeF.class);
 
@@ -1478,6 +1528,7 @@
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE
      */
+    @PublicKey
     public static final Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE =
             new Key<android.util.Size>("android.sensor.info.pixelArraySize", android.util.Size.class);
 
@@ -1495,6 +1546,7 @@
      *
      * @see CameraCharacteristics#SENSOR_BLACK_LEVEL_PATTERN
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_INFO_WHITE_LEVEL =
             new Key<Integer>("android.sensor.info.whiteLevel", int.class);
 
@@ -1507,6 +1559,7 @@
      * @see #SENSOR_INFO_TIMESTAMP_CALIBRATION_UNCALIBRATED
      * @see #SENSOR_INFO_TIMESTAMP_CALIBRATION_CALIBRATED
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_INFO_TIMESTAMP_CALIBRATION =
             new Key<Integer>("android.sensor.info.timestampCalibration", int.class);
 
@@ -1549,6 +1602,7 @@
      * @see #SENSOR_REFERENCE_ILLUMINANT1_D50
      * @see #SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_REFERENCE_ILLUMINANT1 =
             new Key<Integer>("android.sensor.referenceIlluminant1", int.class);
 
@@ -1569,6 +1623,7 @@
      * @see CameraCharacteristics#SENSOR_FORWARD_MATRIX2
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
+    @PublicKey
     public static final Key<Byte> SENSOR_REFERENCE_ILLUMINANT2 =
             new Key<Byte>("android.sensor.referenceIlluminant2", byte.class);
 
@@ -1587,6 +1642,7 @@
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> SENSOR_CALIBRATION_TRANSFORM1 =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.sensor.calibrationTransform1", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -1608,6 +1664,7 @@
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> SENSOR_CALIBRATION_TRANSFORM2 =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.sensor.calibrationTransform2", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -1630,6 +1687,7 @@
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> SENSOR_COLOR_TRANSFORM1 =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.sensor.colorTransform1", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -1654,6 +1712,7 @@
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> SENSOR_COLOR_TRANSFORM2 =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.sensor.colorTransform2", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -1674,6 +1733,7 @@
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> SENSOR_FORWARD_MATRIX1 =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.sensor.forwardMatrix1", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -1696,6 +1756,7 @@
      *
      * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> SENSOR_FORWARD_MATRIX2 =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.sensor.forwardMatrix2", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -1714,6 +1775,7 @@
      * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
      * @see CameraCharacteristics#SENSOR_INFO_WHITE_LEVEL
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.BlackLevelPattern> SENSOR_BLACK_LEVEL_PATTERN =
             new Key<android.hardware.camera2.params.BlackLevelPattern>("android.sensor.blackLevelPattern", android.hardware.camera2.params.BlackLevelPattern.class);
 
@@ -1732,6 +1794,7 @@
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#SENSOR_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_MAX_ANALOG_SENSITIVITY =
             new Key<Integer>("android.sensor.maxAnalogSensitivity", int.class);
 
@@ -1742,6 +1805,7 @@
      * direction of rolling shutter readout, which is from top
      * to bottom in the sensor's coordinate system</p>
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_ORIENTATION =
             new Key<Integer>("android.sensor.orientation", int.class);
 
@@ -1768,6 +1832,7 @@
      *
      * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
      */
+    @PublicKey
     public static final Key<android.util.Pair<Double,Double>[]> SENSOR_NOISE_PROFILE =
             new Key<android.util.Pair<Double,Double>[]>("android.sensor.noiseProfile", new TypeReference<android.util.Pair<Double,Double>[]>() {{ }});
 
@@ -1778,6 +1843,7 @@
      *
      * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
      */
+    @PublicKey
     public static final Key<int[]> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
             new Key<int[]>("android.sensor.availableTestPatternModes", int[].class);
 
@@ -1792,6 +1858,7 @@
      * android.statistics.faceIds and
      * android.statistics.faceLandmarks outputs.</p>
      */
+    @PublicKey
     public static final Key<int[]> STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES =
             new Key<int[]>("android.statistics.info.availableFaceDetectModes", int[].class);
 
@@ -1799,6 +1866,7 @@
      * <p>The maximum number of simultaneously detectable
      * faces.</p>
      */
+    @PublicKey
     public static final Key<Integer> STATISTICS_INFO_MAX_FACE_COUNT =
             new Key<Integer>("android.statistics.info.maxFaceCount", int.class);
 
@@ -1811,6 +1879,7 @@
      *
      * @see CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE
      */
+    @PublicKey
     public static final Key<boolean[]> STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES =
             new Key<boolean[]>("android.statistics.info.availableHotPixelMapModes", boolean[].class);
 
@@ -1827,6 +1896,7 @@
      *
      * @see CaptureRequest#TONEMAP_CURVE
      */
+    @PublicKey
     public static final Key<Integer> TONEMAP_MAX_CURVE_POINTS =
             new Key<Integer>("android.tonemap.maxCurvePoints", int.class);
 
@@ -1838,6 +1908,7 @@
      *
      * @see CaptureRequest#TONEMAP_MODE
      */
+    @PublicKey
     public static final Key<int[]> TONEMAP_AVAILABLE_TONE_MAP_MODES =
             new Key<int[]>("android.tonemap.availableToneMapModes", int[].class);
 
@@ -1879,6 +1950,7 @@
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
      */
+    @PublicKey
     public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL =
             new Key<Integer>("android.info.supportedHardwareLevel", int.class);
 
@@ -1917,10 +1989,12 @@
      * @see #SYNC_MAX_LATENCY_PER_FRAME_CONTROL
      * @see #SYNC_MAX_LATENCY_UNKNOWN
      */
+    @PublicKey
     public static final Key<Integer> SYNC_MAX_LATENCY =
             new Key<Integer>("android.sync.maxLatency", int.class);
 
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
+
 }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 63130a7..ebbfc63 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -17,6 +17,8 @@
 package android.hardware.camera2;
 
 import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.impl.PublicKey;
+import android.hardware.camera2.impl.SyntheticKey;
 import android.util.Log;
 
 import java.lang.reflect.Field;
@@ -151,7 +153,7 @@
                 }
 
                 if (instance == null || instance.getProtected(key) != null) {
-                    if (shouldKeyBeAdded(key, filterTags)) {
+                    if (shouldKeyBeAdded(key, field, filterTags)) {
                         keyList.add(key);
 
                         if (VERBOSE) {
@@ -168,7 +170,7 @@
     }
 
     @SuppressWarnings("rawtypes")
-    private static <TKey> boolean shouldKeyBeAdded(TKey key, int[] filterTags) {
+    private static <TKey> boolean shouldKeyBeAdded(TKey key, Field field, int[] filterTags) {
         if (key == null) {
             throw new NullPointerException("key must not be null");
         }
@@ -189,11 +191,27 @@
             throw new IllegalArgumentException("key type must be that of a metadata key");
         }
 
+        if (field.getAnnotation(PublicKey.class) == null) {
+            // Never expose @hide keys up to the API user
+            return false;
+        }
+
         // No filtering necessary
         if (filterTags == null) {
             return true;
         }
 
+        if (field.getAnnotation(SyntheticKey.class) != null) {
+            // This key is synthetic, so calling #getTag will throw IAE
+
+            // TODO: don't just assume all public+synthetic keys are always available
+            return true;
+        }
+
+        /*
+         * Regular key: look up it's native tag and see if it's in filterTags
+         */
+
         int keyTag = nativeKey.getTag();
 
         // non-negative result is returned iff the value is in the array
@@ -1189,7 +1207,8 @@
      * image while recording video) use case.</p>
      * <p>The camera device should take the highest-quality image
      * possible (given the other settings) without disrupting the
-     * frame rate of video recording.  </p>
+     * frame rate of video recording.<br />
+     * </p>
      * @see CaptureRequest#CONTROL_CAPTURE_INTENT
      */
     public static final int CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT = 4;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 964f4f3..97077e6 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -16,13 +16,13 @@
 
 package android.hardware.camera2;
 
-import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.impl.PublicKey;
+import android.hardware.camera2.impl.SyntheticKey;
 import android.hardware.camera2.utils.HashCodeHelpers;
 import android.hardware.camera2.utils.TypeReference;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Rational;
 import android.view.Surface;
 
 import java.util.Collection;
@@ -526,6 +526,7 @@
      * @see #COLOR_CORRECTION_MODE_FAST
      * @see #COLOR_CORRECTION_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> COLOR_CORRECTION_MODE =
             new Key<Integer>("android.colorCorrection.mode", int.class);
 
@@ -544,6 +545,7 @@
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> COLOR_CORRECTION_TRANSFORM =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.colorCorrection.transform", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -560,6 +562,7 @@
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.RggbChannelVector> COLOR_CORRECTION_GAINS =
             new Key<android.hardware.camera2.params.RggbChannelVector>("android.colorCorrection.gains", android.hardware.camera2.params.RggbChannelVector.class);
 
@@ -583,6 +586,7 @@
      * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_FAST
      * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> COLOR_CORRECTION_ABERRATION_CORRECTION_MODE =
             new Key<Integer>("android.colorCorrection.aberrationCorrectionMode", int.class);
 
@@ -626,6 +630,7 @@
      * @see #CONTROL_AE_ANTIBANDING_MODE_60HZ
      * @see #CONTROL_AE_ANTIBANDING_MODE_AUTO
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_ANTIBANDING_MODE =
             new Key<Integer>("android.control.aeAntibandingMode", int.class);
 
@@ -654,6 +659,7 @@
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureResult#CONTROL_AE_STATE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION =
             new Key<Integer>("android.control.aeExposureCompensation", int.class);
 
@@ -680,6 +686,7 @@
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      * @see CaptureRequest#SENSOR_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Boolean> CONTROL_AE_LOCK =
             new Key<Boolean>("android.control.aeLock", boolean.class);
 
@@ -717,6 +724,7 @@
      * @see #CONTROL_AE_MODE_ON_ALWAYS_FLASH
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_MODE =
             new Key<Integer>("android.control.aeMode", int.class);
 
@@ -742,6 +750,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AE_REGIONS =
             new Key<android.hardware.camera2.params.MeteringRectangle[]>("android.control.aeRegions", android.hardware.camera2.params.MeteringRectangle[].class);
 
@@ -753,6 +762,7 @@
      *
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      */
+    @PublicKey
     public static final Key<android.util.Range<Integer>> CONTROL_AE_TARGET_FPS_RANGE =
             new Key<android.util.Range<Integer>>("android.control.aeTargetFpsRange", new TypeReference<android.util.Range<Integer>>() {{ }});
 
@@ -780,6 +790,7 @@
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_START
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
             new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
 
@@ -802,6 +813,7 @@
      * @see #CONTROL_AF_MODE_CONTINUOUS_PICTURE
      * @see #CONTROL_AF_MODE_EDOF
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AF_MODE =
             new Key<Integer>("android.control.afMode", int.class);
 
@@ -827,6 +839,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AF_REGIONS =
             new Key<android.hardware.camera2.params.MeteringRectangle[]>("android.control.afRegions", android.hardware.camera2.params.MeteringRectangle[].class);
 
@@ -849,6 +862,7 @@
      * @see #CONTROL_AF_TRIGGER_START
      * @see #CONTROL_AF_TRIGGER_CANCEL
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AF_TRIGGER =
             new Key<Integer>("android.control.afTrigger", int.class);
 
@@ -861,6 +875,7 @@
      *
      * @see CaptureRequest#CONTROL_AWB_MODE
      */
+    @PublicKey
     public static final Key<Boolean> CONTROL_AWB_LOCK =
             new Key<Boolean>("android.control.awbLock", boolean.class);
 
@@ -899,6 +914,7 @@
      * @see #CONTROL_AWB_MODE_TWILIGHT
      * @see #CONTROL_AWB_MODE_SHADE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AWB_MODE =
             new Key<Integer>("android.control.awbMode", int.class);
 
@@ -924,6 +940,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS =
             new Key<android.hardware.camera2.params.MeteringRectangle[]>("android.control.awbRegions", android.hardware.camera2.params.MeteringRectangle[].class);
 
@@ -948,6 +965,7 @@
      * @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
      * @see #CONTROL_CAPTURE_INTENT_MANUAL
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_CAPTURE_INTENT =
             new Key<Integer>("android.control.captureIntent", int.class);
 
@@ -973,6 +991,7 @@
      * @see #CONTROL_EFFECT_MODE_BLACKBOARD
      * @see #CONTROL_EFFECT_MODE_AQUA
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_EFFECT_MODE =
             new Key<Integer>("android.control.effectMode", int.class);
 
@@ -1001,6 +1020,7 @@
      * @see #CONTROL_MODE_USE_SCENE_MODE
      * @see #CONTROL_MODE_OFF_KEEP_STATE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_MODE =
             new Key<Integer>("android.control.mode", int.class);
 
@@ -1042,6 +1062,7 @@
      * @see #CONTROL_SCENE_MODE_BARCODE
      * @see #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_SCENE_MODE =
             new Key<Integer>("android.control.sceneMode", int.class);
 
@@ -1066,6 +1087,7 @@
      * @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
      * @see #CONTROL_VIDEO_STABILIZATION_MODE_ON
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_VIDEO_STABILIZATION_MODE =
             new Key<Integer>("android.control.videoStabilizationMode", int.class);
 
@@ -1086,6 +1108,7 @@
      * @see #EDGE_MODE_FAST
      * @see #EDGE_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> EDGE_MODE =
             new Key<Integer>("android.edge.mode", int.class);
 
@@ -1113,6 +1136,7 @@
      * @see #FLASH_MODE_SINGLE
      * @see #FLASH_MODE_TORCH
      */
+    @PublicKey
     public static final Key<Integer> FLASH_MODE =
             new Key<Integer>("android.flash.mode", int.class);
 
@@ -1129,12 +1153,15 @@
      * @see #HOT_PIXEL_MODE_FAST
      * @see #HOT_PIXEL_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> HOT_PIXEL_MODE =
             new Key<Integer>("android.hotPixel.mode", int.class);
 
     /**
      * <p>A location object to use when generating image GPS metadata.</p>
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<android.location.Location> JPEG_GPS_LOCATION =
             new Key<android.location.Location>("android.jpeg.gpsLocation", android.location.Location.class);
 
@@ -1166,6 +1193,7 @@
      * <p>Orientation of JPEG image to
      * write</p>
      */
+    @PublicKey
     public static final Key<Integer> JPEG_ORIENTATION =
             new Key<Integer>("android.jpeg.orientation", int.class);
 
@@ -1174,6 +1202,7 @@
      * image.</p>
      * <p>85-95 is typical usage range.</p>
      */
+    @PublicKey
     public static final Key<Byte> JPEG_QUALITY =
             new Key<Byte>("android.jpeg.quality", byte.class);
 
@@ -1181,6 +1210,7 @@
      * <p>Compression quality of JPEG
      * thumbnail.</p>
      */
+    @PublicKey
     public static final Key<Byte> JPEG_THUMBNAIL_QUALITY =
             new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
 
@@ -1197,6 +1227,7 @@
      * generate the thumbnail image. The thumbnail image will always have a smaller Field
      * Of View (FOV) than the primary image when aspect ratios differ.</p>
      */
+    @PublicKey
     public static final Key<android.util.Size> JPEG_THUMBNAIL_SIZE =
             new Key<android.util.Size>("android.jpeg.thumbnailSize", android.util.Size.class);
 
@@ -1226,6 +1257,7 @@
      * @see CaptureRequest#SENSOR_FRAME_DURATION
      * @see CaptureRequest#SENSOR_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Float> LENS_APERTURE =
             new Key<Float>("android.lens.aperture", float.class);
 
@@ -1249,6 +1281,7 @@
      * @see CameraCharacteristics#LENS_INFO_AVAILABLE_FILTER_DENSITIES
      * @see CaptureResult#LENS_STATE
      */
+    @PublicKey
     public static final Key<Float> LENS_FILTER_DENSITY =
             new Key<Float>("android.lens.filterDensity", float.class);
 
@@ -1268,6 +1301,7 @@
      * @see CaptureRequest#LENS_FOCUS_DISTANCE
      * @see CaptureResult#LENS_STATE
      */
+    @PublicKey
     public static final Key<Float> LENS_FOCAL_LENGTH =
             new Key<Float>("android.lens.focalLength", float.class);
 
@@ -1285,6 +1319,7 @@
      * @see CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE
      * @see CaptureResult#LENS_STATE
      */
+    @PublicKey
     public static final Key<Float> LENS_FOCUS_DISTANCE =
             new Key<Float>("android.lens.focusDistance", float.class);
 
@@ -1314,6 +1349,7 @@
      * @see #LENS_OPTICAL_STABILIZATION_MODE_OFF
      * @see #LENS_OPTICAL_STABILIZATION_MODE_ON
      */
+    @PublicKey
     public static final Key<Integer> LENS_OPTICAL_STABILIZATION_MODE =
             new Key<Integer>("android.lens.opticalStabilizationMode", int.class);
 
@@ -1334,6 +1370,7 @@
      * @see #NOISE_REDUCTION_MODE_FAST
      * @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> NOISE_REDUCTION_MODE =
             new Key<Integer>("android.noiseReduction.mode", int.class);
 
@@ -1381,6 +1418,7 @@
      * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
             new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
 
@@ -1390,6 +1428,7 @@
      * <p>If the sensor can't expose this exact duration, it should shorten the
      * duration exposed to the nearest possible value (rather than expose longer).</p>
      */
+    @PublicKey
     public static final Key<Long> SENSOR_EXPOSURE_TIME =
             new Key<Long>("android.sensor.exposureTime", long.class);
 
@@ -1468,6 +1507,7 @@
      *
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      */
+    @PublicKey
     public static final Key<Long> SENSOR_FRAME_DURATION =
             new Key<Long>("android.sensor.frameDuration", long.class);
 
@@ -1487,6 +1527,7 @@
      * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
      * @see CameraCharacteristics#SENSOR_MAX_ANALOG_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_SENSITIVITY =
             new Key<Integer>("android.sensor.sensitivity", int.class);
 
@@ -1503,6 +1544,7 @@
      *
      * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
      */
+    @PublicKey
     public static final Key<int[]> SENSOR_TEST_PATTERN_DATA =
             new Key<int[]>("android.sensor.testPatternData", int[].class);
 
@@ -1523,6 +1565,7 @@
      * @see #SENSOR_TEST_PATTERN_MODE_PN9
      * @see #SENSOR_TEST_PATTERN_MODE_CUSTOM1
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_TEST_PATTERN_MODE =
             new Key<Integer>("android.sensor.testPatternMode", int.class);
 
@@ -1561,6 +1604,7 @@
      * @see #SHADING_MODE_FAST
      * @see #SHADING_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> SHADING_MODE =
             new Key<Integer>("android.shading.mode", int.class);
 
@@ -1577,6 +1621,7 @@
      * @see #STATISTICS_FACE_DETECT_MODE_SIMPLE
      * @see #STATISTICS_FACE_DETECT_MODE_FULL
      */
+    @PublicKey
     public static final Key<Integer> STATISTICS_FACE_DETECT_MODE =
             new Key<Integer>("android.statistics.faceDetectMode", int.class);
 
@@ -1589,6 +1634,7 @@
      * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
      * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES
      */
+    @PublicKey
     public static final Key<Boolean> STATISTICS_HOT_PIXEL_MAP_MODE =
             new Key<Boolean>("android.statistics.hotPixelMapMode", boolean.class);
 
@@ -1601,6 +1647,7 @@
      * @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
      * @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
      */
+    @PublicKey
     public static final Key<Integer> STATISTICS_LENS_SHADING_MAP_MODE =
             new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
 
@@ -1730,6 +1777,8 @@
      * @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
      * @see CaptureRequest#TONEMAP_MODE
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<android.hardware.camera2.params.TonemapCurve> TONEMAP_CURVE =
             new Key<android.hardware.camera2.params.TonemapCurve>("android.tonemap.curve", android.hardware.camera2.params.TonemapCurve.class);
 
@@ -1763,6 +1812,7 @@
      * @see #TONEMAP_MODE_FAST
      * @see #TONEMAP_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> TONEMAP_MODE =
             new Key<Integer>("android.tonemap.mode", int.class);
 
@@ -1821,10 +1871,12 @@
      * other request parameters require a black level recalculation
      * or reset.</p>
      */
+    @PublicKey
     public static final Key<Boolean> BLACK_LEVEL_LOCK =
             new Key<Boolean>("android.blackLevel.lock", boolean.class);
 
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
+
 }
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 956e64f..c9774ed 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -17,6 +17,8 @@
 package android.hardware.camera2;
 
 import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.impl.PublicKey;
+import android.hardware.camera2.impl.SyntheticKey;
 import android.hardware.camera2.utils.TypeReference;
 import android.util.Log;
 import android.util.Rational;
@@ -365,6 +367,7 @@
      * @see #COLOR_CORRECTION_MODE_FAST
      * @see #COLOR_CORRECTION_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> COLOR_CORRECTION_MODE =
             new Key<Integer>("android.colorCorrection.mode", int.class);
 
@@ -383,6 +386,7 @@
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.ColorSpaceTransform> COLOR_CORRECTION_TRANSFORM =
             new Key<android.hardware.camera2.params.ColorSpaceTransform>("android.colorCorrection.transform", android.hardware.camera2.params.ColorSpaceTransform.class);
 
@@ -399,6 +403,7 @@
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.RggbChannelVector> COLOR_CORRECTION_GAINS =
             new Key<android.hardware.camera2.params.RggbChannelVector>("android.colorCorrection.gains", android.hardware.camera2.params.RggbChannelVector.class);
 
@@ -422,6 +427,7 @@
      * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_FAST
      * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> COLOR_CORRECTION_ABERRATION_CORRECTION_MODE =
             new Key<Integer>("android.colorCorrection.aberrationCorrectionMode", int.class);
 
@@ -465,6 +471,7 @@
      * @see #CONTROL_AE_ANTIBANDING_MODE_60HZ
      * @see #CONTROL_AE_ANTIBANDING_MODE_AUTO
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_ANTIBANDING_MODE =
             new Key<Integer>("android.control.aeAntibandingMode", int.class);
 
@@ -493,6 +500,7 @@
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureResult#CONTROL_AE_STATE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION =
             new Key<Integer>("android.control.aeExposureCompensation", int.class);
 
@@ -519,6 +527,7 @@
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      * @see CaptureRequest#SENSOR_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Boolean> CONTROL_AE_LOCK =
             new Key<Boolean>("android.control.aeLock", boolean.class);
 
@@ -556,6 +565,7 @@
      * @see #CONTROL_AE_MODE_ON_ALWAYS_FLASH
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_MODE =
             new Key<Integer>("android.control.aeMode", int.class);
 
@@ -581,6 +591,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AE_REGIONS =
             new Key<android.hardware.camera2.params.MeteringRectangle[]>("android.control.aeRegions", android.hardware.camera2.params.MeteringRectangle[].class);
 
@@ -592,6 +603,7 @@
      *
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      */
+    @PublicKey
     public static final Key<android.util.Range<Integer>> CONTROL_AE_TARGET_FPS_RANGE =
             new Key<android.util.Range<Integer>>("android.control.aeTargetFpsRange", new TypeReference<android.util.Range<Integer>>() {{ }});
 
@@ -619,6 +631,7 @@
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_START
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
             new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
 
@@ -817,6 +830,7 @@
      * @see #CONTROL_AE_STATE_FLASH_REQUIRED
      * @see #CONTROL_AE_STATE_PRECAPTURE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AE_STATE =
             new Key<Integer>("android.control.aeState", int.class);
 
@@ -839,6 +853,7 @@
      * @see #CONTROL_AF_MODE_CONTINUOUS_PICTURE
      * @see #CONTROL_AF_MODE_EDOF
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AF_MODE =
             new Key<Integer>("android.control.afMode", int.class);
 
@@ -864,6 +879,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AF_REGIONS =
             new Key<android.hardware.camera2.params.MeteringRectangle[]>("android.control.afRegions", android.hardware.camera2.params.MeteringRectangle[].class);
 
@@ -886,6 +902,7 @@
      * @see #CONTROL_AF_TRIGGER_START
      * @see #CONTROL_AF_TRIGGER_CANCEL
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AF_TRIGGER =
             new Key<Integer>("android.control.afTrigger", int.class);
 
@@ -1283,6 +1300,7 @@
      * @see #CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
      * @see #CONTROL_AF_STATE_PASSIVE_UNFOCUSED
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AF_STATE =
             new Key<Integer>("android.control.afState", int.class);
 
@@ -1295,6 +1313,7 @@
      *
      * @see CaptureRequest#CONTROL_AWB_MODE
      */
+    @PublicKey
     public static final Key<Boolean> CONTROL_AWB_LOCK =
             new Key<Boolean>("android.control.awbLock", boolean.class);
 
@@ -1333,6 +1352,7 @@
      * @see #CONTROL_AWB_MODE_TWILIGHT
      * @see #CONTROL_AWB_MODE_SHADE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AWB_MODE =
             new Key<Integer>("android.control.awbMode", int.class);
 
@@ -1358,6 +1378,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS =
             new Key<android.hardware.camera2.params.MeteringRectangle[]>("android.control.awbRegions", android.hardware.camera2.params.MeteringRectangle[].class);
 
@@ -1382,6 +1403,7 @@
      * @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
      * @see #CONTROL_CAPTURE_INTENT_MANUAL
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_CAPTURE_INTENT =
             new Key<Integer>("android.control.captureIntent", int.class);
 
@@ -1512,6 +1534,7 @@
      * @see #CONTROL_AWB_STATE_CONVERGED
      * @see #CONTROL_AWB_STATE_LOCKED
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_AWB_STATE =
             new Key<Integer>("android.control.awbState", int.class);
 
@@ -1537,6 +1560,7 @@
      * @see #CONTROL_EFFECT_MODE_BLACKBOARD
      * @see #CONTROL_EFFECT_MODE_AQUA
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_EFFECT_MODE =
             new Key<Integer>("android.control.effectMode", int.class);
 
@@ -1565,6 +1589,7 @@
      * @see #CONTROL_MODE_USE_SCENE_MODE
      * @see #CONTROL_MODE_OFF_KEEP_STATE
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_MODE =
             new Key<Integer>("android.control.mode", int.class);
 
@@ -1606,6 +1631,7 @@
      * @see #CONTROL_SCENE_MODE_BARCODE
      * @see #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_SCENE_MODE =
             new Key<Integer>("android.control.sceneMode", int.class);
 
@@ -1630,6 +1656,7 @@
      * @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
      * @see #CONTROL_VIDEO_STABILIZATION_MODE_ON
      */
+    @PublicKey
     public static final Key<Integer> CONTROL_VIDEO_STABILIZATION_MODE =
             new Key<Integer>("android.control.videoStabilizationMode", int.class);
 
@@ -1650,6 +1677,7 @@
      * @see #EDGE_MODE_FAST
      * @see #EDGE_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> EDGE_MODE =
             new Key<Integer>("android.edge.mode", int.class);
 
@@ -1677,6 +1705,7 @@
      * @see #FLASH_MODE_SINGLE
      * @see #FLASH_MODE_TORCH
      */
+    @PublicKey
     public static final Key<Integer> FLASH_MODE =
             new Key<Integer>("android.flash.mode", int.class);
 
@@ -1694,6 +1723,7 @@
      * @see #FLASH_STATE_FIRED
      * @see #FLASH_STATE_PARTIAL
      */
+    @PublicKey
     public static final Key<Integer> FLASH_STATE =
             new Key<Integer>("android.flash.state", int.class);
 
@@ -1710,12 +1740,15 @@
      * @see #HOT_PIXEL_MODE_FAST
      * @see #HOT_PIXEL_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> HOT_PIXEL_MODE =
             new Key<Integer>("android.hotPixel.mode", int.class);
 
     /**
      * <p>A location object to use when generating image GPS metadata.</p>
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<android.location.Location> JPEG_GPS_LOCATION =
             new Key<android.location.Location>("android.jpeg.gpsLocation", android.location.Location.class);
 
@@ -1747,6 +1780,7 @@
      * <p>Orientation of JPEG image to
      * write</p>
      */
+    @PublicKey
     public static final Key<Integer> JPEG_ORIENTATION =
             new Key<Integer>("android.jpeg.orientation", int.class);
 
@@ -1755,6 +1789,7 @@
      * image.</p>
      * <p>85-95 is typical usage range.</p>
      */
+    @PublicKey
     public static final Key<Byte> JPEG_QUALITY =
             new Key<Byte>("android.jpeg.quality", byte.class);
 
@@ -1762,6 +1797,7 @@
      * <p>Compression quality of JPEG
      * thumbnail.</p>
      */
+    @PublicKey
     public static final Key<Byte> JPEG_THUMBNAIL_QUALITY =
             new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
 
@@ -1778,6 +1814,7 @@
      * generate the thumbnail image. The thumbnail image will always have a smaller Field
      * Of View (FOV) than the primary image when aspect ratios differ.</p>
      */
+    @PublicKey
     public static final Key<android.util.Size> JPEG_THUMBNAIL_SIZE =
             new Key<android.util.Size>("android.jpeg.thumbnailSize", android.util.Size.class);
 
@@ -1807,6 +1844,7 @@
      * @see CaptureRequest#SENSOR_FRAME_DURATION
      * @see CaptureRequest#SENSOR_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Float> LENS_APERTURE =
             new Key<Float>("android.lens.aperture", float.class);
 
@@ -1830,6 +1868,7 @@
      * @see CameraCharacteristics#LENS_INFO_AVAILABLE_FILTER_DENSITIES
      * @see CaptureResult#LENS_STATE
      */
+    @PublicKey
     public static final Key<Float> LENS_FILTER_DENSITY =
             new Key<Float>("android.lens.filterDensity", float.class);
 
@@ -1849,6 +1888,7 @@
      * @see CaptureRequest#LENS_FOCUS_DISTANCE
      * @see CaptureResult#LENS_STATE
      */
+    @PublicKey
     public static final Key<Float> LENS_FOCAL_LENGTH =
             new Key<Float>("android.lens.focalLength", float.class);
 
@@ -1857,6 +1897,7 @@
      * measured from frontmost surface of the lens.</p>
      * <p>Should be zero for fixed-focus cameras</p>
      */
+    @PublicKey
     public static final Key<Float> LENS_FOCUS_DISTANCE =
             new Key<Float>("android.lens.focusDistance", float.class);
 
@@ -1866,6 +1907,7 @@
      * <p>If variable focus not supported, can still report
      * fixed depth of field range</p>
      */
+    @PublicKey
     public static final Key<android.util.Pair<Float,Float>> LENS_FOCUS_RANGE =
             new Key<android.util.Pair<Float,Float>>("android.lens.focusRange", new TypeReference<android.util.Pair<Float,Float>>() {{ }});
 
@@ -1895,6 +1937,7 @@
      * @see #LENS_OPTICAL_STABILIZATION_MODE_OFF
      * @see #LENS_OPTICAL_STABILIZATION_MODE_ON
      */
+    @PublicKey
     public static final Key<Integer> LENS_OPTICAL_STABILIZATION_MODE =
             new Key<Integer>("android.lens.opticalStabilizationMode", int.class);
 
@@ -1931,6 +1974,7 @@
      * @see #LENS_STATE_STATIONARY
      * @see #LENS_STATE_MOVING
      */
+    @PublicKey
     public static final Key<Integer> LENS_STATE =
             new Key<Integer>("android.lens.state", int.class);
 
@@ -1951,6 +1995,7 @@
      * @see #NOISE_REDUCTION_MODE_FAST
      * @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> NOISE_REDUCTION_MODE =
             new Key<Integer>("android.noiseReduction.mode", int.class);
 
@@ -1982,6 +2027,7 @@
      * frameCount value).</p>
      * <p>Reset on release()</p>
      */
+    @PublicKey
     public static final Key<Integer> REQUEST_FRAME_COUNT =
             new Key<Integer>("android.request.frameCount", int.class);
 
@@ -2005,6 +2051,7 @@
      *
      * @see CameraCharacteristics#REQUEST_PIPELINE_MAX_DEPTH
      */
+    @PublicKey
     public static final Key<Byte> REQUEST_PIPELINE_DEPTH =
             new Key<Byte>("android.request.pipelineDepth", byte.class);
 
@@ -2043,6 +2090,7 @@
      * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
             new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
 
@@ -2052,6 +2100,7 @@
      * <p>If the sensor can't expose this exact duration, it should shorten the
      * duration exposed to the nearest possible value (rather than expose longer).</p>
      */
+    @PublicKey
     public static final Key<Long> SENSOR_EXPOSURE_TIME =
             new Key<Long>("android.sensor.exposureTime", long.class);
 
@@ -2130,6 +2179,7 @@
      *
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      */
+    @PublicKey
     public static final Key<Long> SENSOR_FRAME_DURATION =
             new Key<Long>("android.sensor.frameDuration", long.class);
 
@@ -2149,6 +2199,7 @@
      * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
      * @see CameraCharacteristics#SENSOR_MAX_ANALOG_SENSITIVITY
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_SENSITIVITY =
             new Key<Integer>("android.sensor.sensitivity", int.class);
 
@@ -2171,6 +2222,7 @@
      *
      * @see CameraCharacteristics#SENSOR_INFO_TIMESTAMP_CALIBRATION
      */
+    @PublicKey
     public static final Key<Long> SENSOR_TIMESTAMP =
             new Key<Long>("android.sensor.timestamp", long.class);
 
@@ -2185,6 +2237,7 @@
      * <p>The order of the values is R, G, B; where R is in the lowest index.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
+    @PublicKey
     public static final Key<Rational[]> SENSOR_NEUTRAL_COLOR_POINT =
             new Key<Rational[]>("android.sensor.neutralColorPoint", Rational[].class);
 
@@ -2222,6 +2275,7 @@
      * </ul>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
+    @PublicKey
     public static final Key<Float> SENSOR_GREEN_SPLIT =
             new Key<Float>("android.sensor.greenSplit", float.class);
 
@@ -2238,6 +2292,7 @@
      *
      * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
      */
+    @PublicKey
     public static final Key<int[]> SENSOR_TEST_PATTERN_DATA =
             new Key<int[]>("android.sensor.testPatternData", int[].class);
 
@@ -2258,6 +2313,7 @@
      * @see #SENSOR_TEST_PATTERN_MODE_PN9
      * @see #SENSOR_TEST_PATTERN_MODE_CUSTOM1
      */
+    @PublicKey
     public static final Key<Integer> SENSOR_TEST_PATTERN_MODE =
             new Key<Integer>("android.sensor.testPatternMode", int.class);
 
@@ -2272,6 +2328,7 @@
      *
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<Long> SENSOR_ROLLING_SHUTTER_SKEW =
             new Key<Long>("android.sensor.rollingShutterSkew", long.class);
 
@@ -2310,6 +2367,7 @@
      * @see #SHADING_MODE_FAST
      * @see #SHADING_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> SHADING_MODE =
             new Key<Integer>("android.shading.mode", int.class);
 
@@ -2326,6 +2384,7 @@
      * @see #STATISTICS_FACE_DETECT_MODE_SIMPLE
      * @see #STATISTICS_FACE_DETECT_MODE_FULL
      */
+    @PublicKey
     public static final Key<Integer> STATISTICS_FACE_DETECT_MODE =
             new Key<Integer>("android.statistics.faceDetectMode", int.class);
 
@@ -2388,6 +2447,8 @@
      *
      * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<android.hardware.camera2.params.Face[]> STATISTICS_FACES =
             new Key<android.hardware.camera2.params.Face[]>("android.statistics.faces", android.hardware.camera2.params.Face[].class);
 
@@ -2434,6 +2495,7 @@
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
      */
+    @PublicKey
     public static final Key<android.hardware.camera2.params.LensShadingMap> STATISTICS_LENS_SHADING_CORRECTION_MAP =
             new Key<android.hardware.camera2.params.LensShadingMap>("android.statistics.lensShadingCorrectionMap", android.hardware.camera2.params.LensShadingMap.class);
 
@@ -2554,6 +2616,7 @@
      * @see #STATISTICS_SCENE_FLICKER_50HZ
      * @see #STATISTICS_SCENE_FLICKER_60HZ
      */
+    @PublicKey
     public static final Key<Integer> STATISTICS_SCENE_FLICKER =
             new Key<Integer>("android.statistics.sceneFlicker", int.class);
 
@@ -2566,6 +2629,7 @@
      * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
      * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES
      */
+    @PublicKey
     public static final Key<Boolean> STATISTICS_HOT_PIXEL_MAP_MODE =
             new Key<Boolean>("android.statistics.hotPixelMapMode", boolean.class);
 
@@ -2581,6 +2645,7 @@
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
      */
+    @PublicKey
     public static final Key<android.graphics.Point[]> STATISTICS_HOT_PIXEL_MAP =
             new Key<android.graphics.Point[]>("android.statistics.hotPixelMap", android.graphics.Point[].class);
 
@@ -2593,6 +2658,7 @@
      * @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
      * @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
      */
+    @PublicKey
     public static final Key<Integer> STATISTICS_LENS_SHADING_MAP_MODE =
             new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
 
@@ -2722,6 +2788,8 @@
      * @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
      * @see CaptureRequest#TONEMAP_MODE
      */
+    @PublicKey
+    @SyntheticKey
     public static final Key<android.hardware.camera2.params.TonemapCurve> TONEMAP_CURVE =
             new Key<android.hardware.camera2.params.TonemapCurve>("android.tonemap.curve", android.hardware.camera2.params.TonemapCurve.class);
 
@@ -2755,6 +2823,7 @@
      * @see #TONEMAP_MODE_FAST
      * @see #TONEMAP_MODE_HIGH_QUALITY
      */
+    @PublicKey
     public static final Key<Integer> TONEMAP_MODE =
             new Key<Integer>("android.tonemap.mode", int.class);
 
@@ -2784,6 +2853,7 @@
      *
      * @see CaptureRequest#BLACK_LEVEL_LOCK
      */
+    @PublicKey
     public static final Key<Boolean> BLACK_LEVEL_LOCK =
             new Key<Boolean>("android.blackLevel.lock", boolean.class);
 
@@ -2851,4 +2921,5 @@
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
+
 }
diff --git a/core/java/android/hardware/camera2/impl/ListenerProxies.java b/core/java/android/hardware/camera2/impl/ListenerProxies.java
index 04c43e3..ab9a4d5 100644
--- a/core/java/android/hardware/camera2/impl/ListenerProxies.java
+++ b/core/java/android/hardware/camera2/impl/ListenerProxies.java
@@ -1,3 +1,18 @@
+/*
+ * 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.hardware.camera2.impl;
 
 import android.hardware.camera2.CameraCaptureSession;
diff --git a/core/java/android/hardware/camera2/impl/PublicKey.java b/core/java/android/hardware/camera2/impl/PublicKey.java
new file mode 100644
index 0000000..d894c1f
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/PublicKey.java
@@ -0,0 +1,32 @@
+/*
+ * 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.hardware.camera2.impl;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Denote a static field {@code Key} as being public-visible (in the SDK).
+ *
+ * <p>Keys without this annotated are assumed to be {@code @hide}.</p>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface PublicKey {
+
+}
diff --git a/core/java/android/hardware/camera2/impl/SyntheticKey.java b/core/java/android/hardware/camera2/impl/SyntheticKey.java
new file mode 100644
index 0000000..034a04939
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/SyntheticKey.java
@@ -0,0 +1,36 @@
+/*
+ * 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.hardware.camera2.impl;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Denote a static field {@code Key} as being synthetic (i.e. not having a native
+ * tag one-to-one counterpart).
+ *
+ * <p>Keys without this annotated are assumed to always have a native counter-part.</p>
+ *
+ * <p>In particular a key with a native counter-part will always have it's {@code #getTag}
+ * method succeed.</p>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface SyntheticKey {
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 519bbb6..157c159 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -25,6 +25,7 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.params.StreamConfiguration;
 import android.hardware.camera2.params.StreamConfigurationDuration;
@@ -444,6 +445,120 @@
         m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
 
         /*
+         * request.availableCharacteristicsKeys
+         */
+        {
+            // TODO: check if the underlying key is supported before listing a key as available
+
+            // Note: We only list public keys. Native HALs should list ALL keys regardless of visibility.
+
+            Key<?> availableKeys[] = new Key<?>[] {
+                    CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES          ,
+                    CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES                      ,
+                    CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES          ,
+                    CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE                   ,
+                    CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP                    ,
+                    CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES                      ,
+                    CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS                       ,
+                    CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES                   ,
+                    CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES     ,
+                    CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES                     ,
+                    CameraCharacteristics.CONTROL_MAX_REGIONS                             ,
+                    CameraCharacteristics.FLASH_INFO_AVAILABLE                            ,
+                    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL                   ,
+                    CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES                  ,
+                    CameraCharacteristics.LENS_FACING                                     ,
+                    CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS               ,
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES                  ,
+                    CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS                  ,
+                    CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT                    ,
+                    CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH                      ,
+                    CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM               ,
+//                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP                 ,
+                    CameraCharacteristics.SCALER_CROPPING_TYPE                            ,
+                    CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES             ,
+                    CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE                   ,
+                    CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE                       ,
+                    CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE                    ,
+                    CameraCharacteristics.SENSOR_ORIENTATION                              ,
+                    CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES     ,
+                    CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT                  ,
+                    CameraCharacteristics.SYNC_MAX_LATENCY                                ,
+            };
+            m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, getTagsForKeys(availableKeys));
+        }
+
+        /*
+         * request.availableRequestKeys
+         */
+        {
+            CaptureRequest.Key<?> availableKeys[] = new CaptureRequest.Key<?>[] {
+                    CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
+                    CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
+                    CaptureRequest.CONTROL_AE_LOCK,
+                    CaptureRequest.CONTROL_AE_MODE,
+                    CaptureRequest.CONTROL_AE_REGIONS,
+                    CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
+                    CaptureRequest.CONTROL_AF_MODE,
+                    CaptureRequest.CONTROL_AF_REGIONS,
+                    CaptureRequest.CONTROL_AF_TRIGGER,
+                    CaptureRequest.CONTROL_AWB_LOCK,
+                    CaptureRequest.CONTROL_AWB_MODE,
+                    CaptureRequest.CONTROL_CAPTURE_INTENT,
+                    CaptureRequest.CONTROL_EFFECT_MODE,
+                    CaptureRequest.CONTROL_MODE,
+                    CaptureRequest.CONTROL_SCENE_MODE,
+                    CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
+                    CaptureRequest.FLASH_MODE,
+                    CaptureRequest.JPEG_GPS_COORDINATES,
+                    CaptureRequest.JPEG_GPS_PROCESSING_METHOD,
+                    CaptureRequest.JPEG_GPS_TIMESTAMP,
+                    CaptureRequest.JPEG_ORIENTATION,
+                    CaptureRequest.JPEG_QUALITY,
+                    CaptureRequest.JPEG_THUMBNAIL_QUALITY,
+                    CaptureRequest.JPEG_THUMBNAIL_SIZE,
+                    CaptureRequest.LENS_FOCAL_LENGTH,
+                    CaptureRequest.SCALER_CROP_REGION,
+                    CaptureRequest.STATISTICS_FACE_DETECT_MODE,
+            };
+            m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableKeys));
+        }
+
+        /*
+         * request.availableResultKeys
+         */
+        {
+            CaptureResult.Key<?> availableKeys[] = new CaptureResult.Key<?>[] {
+                    CaptureResult.CONTROL_AE_ANTIBANDING_MODE                      ,
+                    CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION                 ,
+                    CaptureResult.CONTROL_AE_LOCK                                  ,
+                    CaptureResult.CONTROL_AE_MODE                                  ,
+                    CaptureResult.CONTROL_AE_REGIONS                               ,
+                    CaptureResult.CONTROL_AF_MODE                                  ,
+                    CaptureResult.CONTROL_AF_REGIONS                               ,
+                    CaptureResult.CONTROL_AF_STATE                                 ,
+                    CaptureResult.CONTROL_AWB_MODE                                 ,
+                    CaptureResult.CONTROL_AWB_LOCK                                 ,
+                    CaptureResult.CONTROL_MODE                                     ,
+                    CaptureResult.FLASH_MODE                                       ,
+                    CaptureResult.JPEG_GPS_COORDINATES                             ,
+                    CaptureResult.JPEG_GPS_PROCESSING_METHOD                       ,
+                    CaptureResult.JPEG_GPS_TIMESTAMP                               ,
+                    CaptureResult.JPEG_ORIENTATION                                 ,
+                    CaptureResult.JPEG_QUALITY                                     ,
+                    CaptureResult.JPEG_THUMBNAIL_QUALITY                           ,
+                    CaptureResult.LENS_FOCAL_LENGTH                                ,
+                    CaptureResult.REQUEST_FRAME_COUNT                              ,
+                    CaptureResult.REQUEST_PIPELINE_DEPTH                           ,
+                    CaptureResult.SCALER_CROP_REGION                               ,
+                    CaptureResult.SENSOR_TIMESTAMP                                 ,
+                    CaptureResult.STATISTICS_FACE_DETECT_MODE                      ,
+//                    CaptureResult.STATISTICS_FACES                                 ,
+            };
+            m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableKeys));
+        }
+
+        /*
          * request.maxNumOutputStreams
          */
         int[] outputStreams = {
@@ -649,4 +764,34 @@
         // TODO: map other request template values
         return m;
     }
+
+    private static int[] getTagsForKeys(Key<?>[] keys) {
+        int[] tags = new int[keys.length];
+
+        for (int i = 0; i < keys.length; ++i) {
+            tags[i] = keys[i].getNativeKey().getTag();
+        }
+
+        return tags;
+    }
+
+    private static int[] getTagsForKeys(CaptureRequest.Key<?>[] keys) {
+        int[] tags = new int[keys.length];
+
+        for (int i = 0; i < keys.length; ++i) {
+            tags[i] = keys[i].getNativeKey().getTag();
+        }
+
+        return tags;
+    }
+
+    private static int[] getTagsForKeys(CaptureResult.Key<?>[] keys) {
+        int[] tags = new int[keys.length];
+
+        for (int i = 0; i < keys.length; ++i) {
+            tags[i] = keys[i].getNativeKey().getTag();
+        }
+
+        return tags;
+    }
 }
diff --git a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
index ae0bda1..acf92f1 100644
--- a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
@@ -57,7 +57,13 @@
     // Value indicating the device is not an active source.
     public static final int DEVICE_INACTIVE = -1;
 
-    // Logical address, phsical address, device type, vendor id and display name
+    /**
+     * Logical address used to indicate the source comes from internal device.
+     * The logical address of TV(0) is used.
+     */
+    public static final int ADDR_INTERNAL = 0;
+
+    // Logical address, physical address, device type, vendor id and display name
     // are immutable value.
     private final int mLogicalAddress;
     private final int mPhysicalAddress;
diff --git a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
new file mode 100644
index 0000000..03efd8c
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
@@ -0,0 +1,415 @@
+/*
+ * 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.hardware.hdmi;
+
+import android.annotation.SystemApi;
+import android.hardware.hdmi.HdmiRecordSources.AnalogueServiceSource;
+import android.hardware.hdmi.HdmiRecordSources.DigitalServiceSource;
+import android.hardware.hdmi.HdmiRecordSources.ExternalPhysicalAddress;
+import android.hardware.hdmi.HdmiRecordSources.ExternalPlugData;
+import android.hardware.hdmi.HdmiRecordSources.RecordSource;
+import android.util.Log;
+
+/**
+ * Container for timer record source used for timer recording. Timer source consists of two parts,
+ * timer info and record source.
+ * <p>
+ * Timer info contains all timing information used for recording. It consists of the following
+ * values.
+ * <ul>
+ * <li>[Day of Month]
+ * <li>[Month of Year]
+ * <li>[Start Time]
+ * <li>[Duration]
+ * <li>[Recording Sequence]
+ * </ul>
+ * <p>
+ * Record source containers all program information used for recording.
+ * For more details, look at {@link HdmiRecordSources}.
+ * <p>
+ * Usage
+ * <pre>
+ * TimeOrDuration startTime = HdmiTimerRecordSources.ofTime(18, 00);  // 6PM.
+ * TimeOrDuration duration = HdmiTimerRecordSource.ofDuration(1, 00);  // 1 hour duration.
+ * // For 1 hour from 6PM, August 10th every SaturDay and Sunday.
+ * TimerInfo timerInfo = HdmiTimerRecordSource.timerInfoOf(10, 8, starTime, duration,
+ *            HdmiTimerRecordSource.RECORDING_SEQUENCE_REPEAT_SATURDAY |
+ *            HdmiTimerRecordSource.RECORDING_SEQUENCE_REPEAT_SUNDAY);
+ * // create digital source.
+ * DigitalServiceSource recordSource = HdmiRecordSource.ofDvb(...);
+ * TimerRecordSource source = ofDigitalSource(timerInfo, recordSource);
+ * </pre>
+ *
+ * @hide
+ */
+@SystemApi
+public class HdmiTimerRecordSources {
+    private static final String TAG = "HdmiTimerRecordingSources";
+
+    private HdmiTimerRecordSources() {}
+
+    /**
+     * Create {@link TimerRecordSource} for digital source which is used for &lt;Set Digital
+     * Timer&gt;.
+     *
+     * @param timerInfo timer info used for timer recording
+     * @param source digital source used for timer recording
+     * @return {@link TimerRecordSource}
+     * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null
+     */
+    public static TimerRecordSource ofDigitalSource(TimerInfo timerInfo,
+            DigitalServiceSource source) {
+        checkTimerRecordSourceInputs(timerInfo, source);
+        return new TimerRecordSource(timerInfo, source);
+    }
+
+    /**
+     * Create {@link TimerRecordSource} for analogue source which is used for &lt;Set Analogue
+     * Timer&gt;.
+     *
+     * @param timerInfo timer info used for timer recording
+     * @param source digital source used for timer recording
+     * @return {@link TimerRecordSource}
+     * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null
+     */
+    public static TimerRecordSource ofAnalogueSource(TimerInfo timerInfo,
+            AnalogueServiceSource source) {
+        checkTimerRecordSourceInputs(timerInfo, source);
+        return new TimerRecordSource(timerInfo, source);
+    }
+
+    /**
+     * Create {@link TimerRecordSource} for external plug which is used for &lt;Set External
+     * Timer&gt;.
+     *
+     * @param timerInfo timer info used for timer recording
+     * @param source digital source used for timer recording
+     * @return {@link TimerRecordSource}
+     * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null
+     */
+    public static TimerRecordSource ofExternalPlug(TimerInfo timerInfo, ExternalPlugData source) {
+        checkTimerRecordSourceInputs(timerInfo, source);
+        return new TimerRecordSource(timerInfo,
+                new ExternalSourceDecorator(source, EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG));
+    }
+
+    /**
+     * Create {@link TimerRecordSource} for external physical address which is used for &lt;Set
+     * External Timer&gt;.
+     *
+     * @param timerInfo timer info used for timer recording
+     * @param source digital source used for timer recording
+     * @return {@link TimerRecordSource}
+     * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null
+     */
+    public static TimerRecordSource ofExternalPhysicalAddress(TimerInfo timerInfo,
+            ExternalPhysicalAddress source) {
+        checkTimerRecordSourceInputs(timerInfo, source);
+        return new TimerRecordSource(timerInfo,
+                new ExternalSourceDecorator(source,
+                        EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS));
+    }
+
+    private static void checkTimerRecordSourceInputs(TimerInfo timerInfo, RecordSource source) {
+        if (timerInfo == null) {
+            Log.w(TAG, "TimerInfo should not be null.");
+            throw new IllegalArgumentException("TimerInfo should not be null.");
+        }
+        if (source == null) {
+            Log.w(TAG, "source should not be null.");
+            throw new IllegalArgumentException("source should not be null.");
+        }
+    }
+
+    /**
+     * Create {@link Duration} for time value.
+     *
+     * @param hour hour in range of [0, 24]
+     * @param minute minute in range of [0, 60]
+     * @return {@link Duration}
+     * @throw IllegalArgumentException if hour or minute is out of range
+     */
+    public static Time ofTime(int hour, int minute) {
+        checkTimeValue(hour, minute);
+        return new Time(hour, minute);
+    }
+
+    private static void checkTimeValue(int hour, int minute) {
+        if (hour < 0 || hour > 24) {
+            throw new IllegalArgumentException("Hour should be in rage of [0, 24]:" + hour);
+        }
+        if (minute < 0 || minute > 60) {
+            throw new IllegalArgumentException("Minute should be in rage of [0, 60]:" + minute);
+        }
+    }
+
+    /**
+     * Create {@link Duration} for duration value.
+     *
+     * @param hour hour in range of [0, 90]
+     * @param minute minute in range of [0, 60]
+     * @return {@link Duration}
+     * @throw IllegalArgumentException if hour or minute is out of range
+     */
+    public static Duration ofDuration(int hour, int minute) {
+        checkDurationValue(hour, minute);
+        return new Duration(hour, minute);
+    }
+
+    private static void checkDurationValue(int hour, int minute) {
+        if (hour < 0 || hour > 99) {
+            throw new IllegalArgumentException("Hour should be in rage of [0, 99]:" + hour);
+        }
+        if (minute < 0 || minute > 60) {
+            throw new IllegalArgumentException("minute should be in rage of [0, 60]:" + minute);
+        }
+    }
+
+    private static class TimeUnit {
+        protected final int mHour;
+        protected final int mMinute;
+
+        protected TimeUnit(int hour, int minute) {
+            mHour = hour;
+            mMinute = minute;
+        }
+
+        protected int toByteArray(byte[] data, int index) {
+            data[index] = toBcdByte(mHour);
+            data[index + 1] = toBcdByte(mMinute);
+            return 2;
+        }
+
+        protected static byte toBcdByte(int value) {
+            int digitOfTen = (value / 10) % 10;
+            int digitOfOne = value % 10;
+            return (byte) ((digitOfTen << 4) | digitOfOne);
+        }
+    }
+
+    /**
+     * Place holder for time value.
+     */
+    public static class Time extends TimeUnit {
+        private Time(int hour, int minute) {
+            super(hour, minute);
+        }
+    }
+
+    /**
+     * Place holder for duration value.
+     */
+    public static class Duration extends TimeUnit {
+        private Duration(int hour, int minute) {
+            super(hour, minute);
+        }
+    }
+
+    /**
+     * Fields for recording sequence.
+     * The following can be merged by OR(|) operation.
+     */
+    public static final int RECORDING_SEQUENCE_REPEAT_ONCE_ONLY = 0;
+    public static final int RECORDING_SEQUENCE_REPEAT_SUNDAY = 1 << 0;
+    public static final int RECORDING_SEQUENCE_REPEAT_MONDAY = 1 << 1;
+    public static final int RECORDING_SEQUENCE_REPEAT_TUESDAY = 1 << 2;
+    public static final int RECORDING_SEQUENCE_REPEAT_WEDNESDAY = 1 << 3;
+    public static final int RECORDING_SEQUENCE_REPEAT_THURSDAY = 1 << 4;
+    public static final int RECORDING_SEQUENCE_REPEAT_FRIDAY = 1 << 5;
+    public static final int RECORDING_SEQUENCE_REPEAT_SATUREDAY = 1 << 6;
+
+    private static final int RECORDING_SEQUENCE_REPEAT_MASK =
+            (RECORDING_SEQUENCE_REPEAT_SUNDAY | RECORDING_SEQUENCE_REPEAT_MONDAY |
+            RECORDING_SEQUENCE_REPEAT_TUESDAY | RECORDING_SEQUENCE_REPEAT_WEDNESDAY |
+            RECORDING_SEQUENCE_REPEAT_THURSDAY | RECORDING_SEQUENCE_REPEAT_FRIDAY |
+            RECORDING_SEQUENCE_REPEAT_SATUREDAY);
+
+    /**
+     * Create {@link TimerInfo} with the given information.
+     *
+     * @param dayOfMonth day of month
+     * @param monthOfYear month of year
+     * @param startTime start time in {@link Time}
+     * @param duration duration in {@link Duration}
+     * @param recordingSequence recording sequence. Use RECORDING_SEQUENCE_REPEAT_ONCE_ONLY for no
+     *            repeat. Otherwise use combination of {@link #RECORDING_SEQUENCE_REPEAT_SUNDAY},
+     *            {@link #RECORDING_SEQUENCE_REPEAT_MONDAY},
+     *            {@link #RECORDING_SEQUENCE_REPEAT_TUESDAY},
+     *            {@link #RECORDING_SEQUENCE_REPEAT_WEDNESDAY},
+     *            {@link #RECORDING_SEQUENCE_REPEAT_THURSDAY},
+     *            {@link #RECORDING_SEQUENCE_REPEAT_FRIDAY},
+     *            {@link #RECORDING_SEQUENCE_REPEAT_SATUREDAY}.
+     * @return {@link TimerInfo}.
+     * @throw IllegalArgumentException if input value is invalid
+     */
+    public static TimerInfo timerInfoOf(int dayOfMonth, int monthOfYear, Time startTime,
+            Duration duration, int recordingSequence) {
+        if (dayOfMonth < 0 || dayOfMonth > 31) {
+            throw new IllegalArgumentException(
+                    "Day of month should be in range of [0, 31]:" + dayOfMonth);
+        }
+        if (monthOfYear < 1 || monthOfYear > 12) {
+            throw new IllegalArgumentException(
+                    "Month of year should be in range of [1, 12]:" + monthOfYear);
+        }
+        checkTimeValue(startTime.mHour, startTime.mMinute);
+        checkDurationValue(duration.mHour, duration.mMinute);
+        // Recording sequence should use least 7 bits or no bits.
+        if ((recordingSequence != 0)
+                && ((recordingSequence & ~RECORDING_SEQUENCE_REPEAT_MASK) != 0)) {
+            throw new IllegalArgumentException(
+                    "Invalid reecording sequence value:" + recordingSequence);
+        }
+
+        return new TimerInfo(dayOfMonth, monthOfYear, startTime, duration, recordingSequence);
+    }
+
+    /**
+     * Container basic timer information. It consists of the following fields.
+     * <ul>
+     * <li>[Day of Month]
+     * <li>[Month of Year]
+     * <li>[Start Time]
+     * <li>[Duration]
+     * <li>[Recording Sequence]
+     * </ul>
+     */
+    public static class TimerInfo {
+        private static final int DAY_OF_MONTH_SIZE = 1;
+        private static final int MONTH_OF_YEAR_SIZE = 1;
+        private static final int START_TIME_SIZE = 2; // 1byte for hour and 1byte for minute.
+        private static final int DURATION_SIZE = 2; // 1byte for hour and 1byte for minute.
+        private static final int RECORDING_SEQUENCE_SIZE = 1;
+        private static final int BASIC_INFO_SIZE = DAY_OF_MONTH_SIZE + MONTH_OF_YEAR_SIZE
+                + START_TIME_SIZE + DURATION_SIZE + RECORDING_SEQUENCE_SIZE;
+
+        /** Day of month. */
+        private final int mDayOfMonth;
+        /** Month of year. */
+        private final int mMonthOfYear;
+        /**
+         * Time of day.
+         * [Hour][Minute]. 0 &lt;= Hour &lt;= 24, 0 &lt;= Minute &lt;= 60 in BCD format.
+         */
+        private final Time mStartTime;
+        /**
+         * Duration. [Hour][Minute].
+         * 0 &lt;= Hour &lt;= 99, 0 &lt;= Minute &lt;= 60 in BCD format.
+         * */
+        private final Duration mDuration;
+        /**
+         * Indicates if recording is repeated and, if so, on which days. For repeated recordings,
+         * the recording sequence value is the bitwise OR of the days when recordings are required.
+         * [Recording Sequence] shall be set to 0x00 when the recording is not repeated. Bit 7 is
+         * reserved and shall be set to zero.
+         */
+        private final int mRecordingSequence;
+
+        private TimerInfo(int dayOfMonth, int monthOfYear, Time startTime,
+                Duration duration, int recordingSequence) {
+            mDayOfMonth = dayOfMonth;
+            mMonthOfYear = monthOfYear;
+            mStartTime = startTime;
+            mDuration = duration;
+            mRecordingSequence = recordingSequence;
+        }
+
+        int toByteArray(byte[] data, int index) {
+            // [Day of Month]
+            data[index] = (byte) mDayOfMonth;
+            index += DAY_OF_MONTH_SIZE;
+            // [Month of Year]
+            data[index] = (byte) mMonthOfYear;
+            index += MONTH_OF_YEAR_SIZE;
+            // [Start Time]
+            index += mStartTime.toByteArray(data, index);
+            index += mDuration.toByteArray(data, index);
+            // [Duration]
+            // [Recording Sequence]
+            data[index] = (byte) mRecordingSequence;
+            return getDataSize();
+        }
+
+        int getDataSize() {
+            return BASIC_INFO_SIZE;
+        }
+    }
+
+    /**
+     * Record source container for timer record. This is used to set parameter for &lt;Set Digital
+     * Timer&gt;, &lt;Set Analogue Timer&gt;, and &lt;Set External Timer&gt; message.
+     * <p>
+     * In order to create this from each source type, use one of helper method.
+     * <ul>
+     * <li>{@link #ofDigitalSource} for digital source
+     * <li>{@link #ofAnalogueSource} for analogue source
+     * <li>{@link #ofExternalPlug} for external plug type
+     * <li>{@link #ofExternalPhysicalAddress} for external physical address type.
+     * </ul>
+     */
+    public static class TimerRecordSource {
+        private final RecordSource mRecordSource;
+        private final TimerInfo mTimerInfo;
+
+        private TimerRecordSource(TimerInfo timerInfo, RecordSource recordSource) {
+            mTimerInfo = timerInfo;
+            mRecordSource = recordSource;
+        }
+
+        int getDataSize() {
+            return mTimerInfo.getDataSize() + mRecordSource.getDataSize(false);
+        }
+
+        int toByteArray(byte[] data, int index) {
+            // Basic infos including [Day of Month] [Month of Year] [Start Time] [Duration]
+            // [Recording Sequence]
+            index += mTimerInfo.toByteArray(data, index);
+            // [Record Source]
+            mRecordSource.toByteArray(false, data, index);
+            return getDataSize();
+        }
+    }
+
+    /**
+     * External source specifier types.
+     */
+    private static final int EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG = 4;
+    private static final int EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS = 5;
+
+    /**
+     * Decorator for external source. Beside digital or analogue source, external source starts with
+     * [External Source Specifier] because it covers both external plug type and external specifier.
+     */
+    private static class ExternalSourceDecorator extends RecordSource {
+        private final RecordSource mRecordSource;
+        private final int mExternalSourceSpecifier;
+
+        private ExternalSourceDecorator(RecordSource recordSource, int externalSourceSpecifier) {
+            // External source has one byte field for [External Source Specifier].
+            super(recordSource.mSourceType, recordSource.getDataSize(false) + 1);
+            mRecordSource = recordSource;
+            mExternalSourceSpecifier = externalSourceSpecifier;
+        }
+
+        @Override
+        int extraParamToByteArray(byte[] data, int index) {
+            data[index] = (byte) mExternalSourceSpecifier;
+            mRecordSource.toByteArray(false, data, index + 1);
+            return getDataSize(false);
+        }
+    }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 6d64a1d..c02ff8a 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -168,29 +168,56 @@
     /**
      * Set {@link RecordRequestListener} to hdmi control service.
      */
-    public void setRecordRequestListener(RecordRequestListener listener) {
+    public void setOneTouchRecordRequestListener(RecordRequestListener listener) {
         try {
-            mService.setRecordRequestListener(getCallbackWrapper(listener));
+            mService.setOneTouchRecordRequestListener(getCallbackWrapper(listener));
         } catch (RemoteException e) {
             Log.e(TAG, "failed to set record request listener: ", e);
         }
     }
 
     /**
-     * Start recording with the given recorder address and recorder source.
-     * <p>Usage
+     * Start one touch recording with the given recorder address and recorder source.
+     * <p>
+     * Usage
      * <pre>
      * HdmiTvClient tvClient = ....;
      * // for own source.
      * OwnSource ownSource = ownHdmiRecordSources.ownSource();
-     * tvClient.startRecord(recorderAddress, ownSource);
+     * tvClient.startOneTouchRecord(recorderAddress, ownSource);
      * </pre>
      */
-    public void startRecord(int recorderAddress, HdmiRecordSources.RecordSource source) {
+    public void startOneTouchRecord(int recorderAddress, HdmiRecordSources.RecordSource source) {
         try {
             byte[] data = new byte[source.getDataSize(true)];
             source.toByteArray(true, data, 0);
-            mService.startRecord(recorderAddress, data);
+            mService.startOneTouchRecord(recorderAddress, data);
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to start record: ", e);
+        }
+    }
+
+    /**
+     * Start timer recording with the given recoder address and recorder source.
+     * <p>
+     * Usage
+     * <pre>
+     * HdmiTvClient tvClient = ....;
+     * // create timer info
+     * TimerInfo timerInfo = HdmiTimerRecourdSources.timerInfoOf(...);
+     * // for digital source.
+     * DigitalServiceSource recordSource = HdmiRecordSources.ofDigitalService(...);
+     * // create timer recording source.
+     * TimerRecordSource source = HdmiTimerRecourdSources.ofDigitalSource(timerInfo, recordSource);
+     * tvClient.startTimerRecording(recorderAddress, source);
+     * </pre>
+     */
+    public void startTimerRecording(int recorderAddress,
+            HdmiTimerRecordSources.TimerRecordSource source) {
+        try {
+            byte[] data = new byte[source.getDataSize()];
+            source.toByteArray(data, 0);
+            mService.startTimerRecording(recorderAddress, data);
         } catch (RemoteException e) {
             Log.e(TAG, "failed to start record: ", e);
         }
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 6f3763b..53b8b3f 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -55,13 +55,14 @@
     void setArcMode(boolean enabled);
     void setOption(int option, int value);
     void setProhibitMode(boolean enabled);
-    oneway void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex);
-    oneway void setSystemAudioMute(boolean mute);
+    void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex);
+    void setSystemAudioMute(boolean mute);
     void setInputChangeListener(IHdmiInputChangeListener listener);
     List<HdmiCecDeviceInfo> getInputDevices();
     void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
             boolean hasVendorId);
     void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
-    void setRecordRequestListener(IHdmiRecordRequestListener listener);
-    void startRecord(int recorderAddress, in byte[] recordSource);
+    void setOneTouchRecordRequestListener(IHdmiRecordRequestListener listener);
+    void startOneTouchRecord(int recorderAddress, in byte[] recordSource);
+    void startTimerRecording(int recorderAddress, in byte[] recordSource);
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8de545e..13364cd 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -543,8 +543,6 @@
 
     private final IConnectivityManager mService;
 
-    private final String mPackageName;
-
     private INetworkManagementService mNMService;
 
     /**
@@ -646,23 +644,6 @@
     }
 
     /**
-     * Checks if the given network type should be exempt from VPN routing rules
-     *
-     * @hide
-     */
-    public static boolean isNetworkTypeExempt(int networkType) {
-        switch (networkType) {
-            case TYPE_MOBILE_MMS:
-            case TYPE_MOBILE_SUPL:
-            case TYPE_MOBILE_HIPRI:
-            case TYPE_MOBILE_IA:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
      * Specifies the preferred network type.  When the device has more
      * than one type available the preferred network type will be used.
      *
@@ -1236,13 +1217,7 @@
      *             {@link #setProcessDefaultNetwork} and {@link Network#getSocketFactory} api.
      */
     public boolean requestRouteToHost(int networkType, int hostAddress) {
-        InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
-
-        if (inetAddress == null) {
-            return false;
-        }
-
-        return requestRouteToHostAddress(networkType, inetAddress);
+        return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress));
     }
 
     /**
@@ -1260,9 +1235,8 @@
      *             {@link #setProcessDefaultNetwork} api.
      */
     public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
-        byte[] address = hostAddress.getAddress();
         try {
-            return mService.requestRouteToHostAddress(networkType, address, mPackageName);
+            return mService.requestRouteToHostAddress(networkType, hostAddress.getAddress());
         } catch (RemoteException e) {
             return false;
         }
@@ -1433,9 +1407,8 @@
     /**
      * {@hide}
      */
-    public ConnectivityManager(IConnectivityManager service, String packageName) {
+    public ConnectivityManager(IConnectivityManager service) {
         mService = checkNotNull(service, "missing IConnectivityManager");
-        mPackageName = checkNotNull(packageName, "missing package name");
     }
 
     /** {@hide} */
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index f61984a..8b12fb8 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -69,9 +69,7 @@
 
     int stopUsingNetworkFeature(int networkType, in String feature);
 
-    boolean requestRouteToHost(int networkType, int hostAddress, String packageName);
-
-    boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, String packageName);
+    boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
 
     /** Policy control over specific {@link NetworkStateTracker}. */
     void setPolicyDataEnable(int networkType, boolean enabled);
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 9b95305..663aa15 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -36,12 +36,6 @@
 
     private static final String TAG = "NetworkUtils";
 
-    /** Bring the named network interface up. */
-    public native static int enableInterface(String interfaceName);
-
-    /** Bring the named network interface down. */
-    public native static int disableInterface(String interfaceName);
-
     /** Setting bit 0 indicates reseting of IPv4 addresses required */
     public static final int RESET_IPV4_ADDRESSES = 0x01;
 
diff --git a/core/java/android/net/PSKKeyManager.java b/core/java/android/net/PskKeyManager.java
similarity index 77%
rename from core/java/android/net/PSKKeyManager.java
rename to core/java/android/net/PskKeyManager.java
index e868c4f..d162282 100644
--- a/core/java/android/net/PSKKeyManager.java
+++ b/core/java/android/net/PskKeyManager.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import com.android.org.conscrypt.PSKKeyManager;
 import java.net.Socket;
 import javax.crypto.SecretKey;
 import javax.net.ssl.SSLEngine;
@@ -40,10 +41,10 @@
  *
  * <h3>Supporting multiple keys</h3>
  *
- * <p>A peer may have multiple keys to choose from. To help choose the right key, during the handshake
- * the server can provide a <em>PSK identity hint</em> to the client, and the client can provide a
- * <em>PSK identity</em> to the server. The contents of these two pieces of information are specific
- * to application-level protocols.</p>
+ * <p>A peer may have multiple keys to choose from. To help choose the right key, during the
+ * handshake the server can provide a <em>PSK identity hint</em> to the client, and the client can
+ * provide a <em>PSK identity</em> to the server. The contents of these two pieces of information
+ * are specific to application-level protocols.</p>
  *
  * <p><em>NOTE: Both the PSK identity hint and the PSK identity are transmitted in cleartext.
  * Moreover, these data are received and processed prior to peer having been authenticated. Thus,
@@ -76,16 +77,20 @@
  * {@link #MAX_IDENTITY_LENGTH_BYTES} and {@link #MAX_IDENTITY_HINT_LENGTH_BYTES}).</li>
  * </ul></p>
  *
+ * <h3>Subclassing</h3>
+ * Subclasses should normally provide their own implementation of {@code getKey} because the default
+ * implementation returns no key, which aborts the handshake.
+ *
  * <h3>Example</h3>
  * The following example illustrates how to create an {@code SSLContext} which enables the use of
  * TLS-PSK in {@code SSLSocket}, {@code SSLServerSocket} and {@code SSLEngine} instances obtained
  * from it.
  * <pre> {@code
- * PSKKeyManager myPskKeyManager = ...;
+ * PskKeyManager pskKeyManager = ...;
  *
  * SSLContext sslContext = SSLContext.getInstance("TLS");
  * sslContext.init(
- *         new KeyManager[] &#123;myPskKeyManager&#125;,
+ *         new KeyManager[] &#123;pskKeyManager&#125;,
  *         new TrustManager[0], // No TrustManagers needed for TLS-PSK
  *         null // Use the default source of entropy
  *         );
@@ -93,7 +98,7 @@
  * SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(...);
  * }</pre>
  */
-public interface PSKKeyManager extends com.android.org.conscrypt.PSKKeyManager {
+public abstract class PskKeyManager implements PSKKeyManager {
     // IMPLEMENTATION DETAILS: This class exists only because the default implemenetation of the
     // TLS/SSL JSSE provider (currently Conscrypt) cannot depend on Android framework classes.
     // As a result, this framework class simply extends the PSKKeyManager interface from Conscrypt
@@ -103,61 +108,83 @@
     /**
      * Maximum supported length (in bytes) for PSK identity hint (in modified UTF-8 representation).
      */
-    int MAX_IDENTITY_HINT_LENGTH_BYTES =
-            com.android.org.conscrypt.PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES;
+    public static final int MAX_IDENTITY_HINT_LENGTH_BYTES =
+            PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES;
 
     /** Maximum supported length (in bytes) for PSK identity (in modified UTF-8 representation). */
-    int MAX_IDENTITY_LENGTH_BYTES =
-            com.android.org.conscrypt.PSKKeyManager.MAX_IDENTITY_LENGTH_BYTES;
+    public static final int MAX_IDENTITY_LENGTH_BYTES = PSKKeyManager.MAX_IDENTITY_LENGTH_BYTES;
 
     /** Maximum supported length (in bytes) for PSK. */
-    int MAX_KEY_LENGTH_BYTES = com.android.org.conscrypt.PSKKeyManager.MAX_KEY_LENGTH_BYTES;
+    public static final int MAX_KEY_LENGTH_BYTES = PSKKeyManager.MAX_KEY_LENGTH_BYTES;
 
     /**
      * Gets the PSK identity hint to report to the client to help agree on the PSK for the provided
      * socket.
      *
+     * <p>
+     * The default implementation returns {@code null}.
+     *
      * @return PSK identity hint to be provided to the client or {@code null} to provide no hint.
      */
     @Override
-    String chooseServerKeyIdentityHint(Socket socket);
+    public String chooseServerKeyIdentityHint(Socket socket) {
+        return null;
+    }
 
     /**
      * Gets the PSK identity hint to report to the client to help agree on the PSK for the provided
      * engine.
      *
+     * <p>
+     * The default implementation returns {@code null}.
+     *
      * @return PSK identity hint to be provided to the client or {@code null} to provide no hint.
      */
     @Override
-    String chooseServerKeyIdentityHint(SSLEngine engine);
+    public String chooseServerKeyIdentityHint(SSLEngine engine) {
+        return null;
+    }
 
     /**
      * Gets the PSK identity to report to the server to help agree on the PSK for the provided
      * socket.
      *
+     * <p>
+     * The default implementation returns an empty string.
+     *
      * @param identityHint identity hint provided by the server or {@code null} if none provided.
      *
      * @return PSK identity to provide to the server. {@code null} is permitted but will be
      *         converted into an empty string.
      */
     @Override
-    String chooseClientKeyIdentity(String identityHint, Socket socket);
+    public String chooseClientKeyIdentity(String identityHint, Socket socket) {
+        return "";
+    }
 
     /**
      * Gets the PSK identity to report to the server to help agree on the PSK for the provided
      * engine.
      *
+     * <p>
+     * The default implementation returns an empty string.
+     *
      * @param identityHint identity hint provided by the server or {@code null} if none provided.
      *
      * @return PSK identity to provide to the server. {@code null} is permitted but will be
      *         converted into an empty string.
      */
     @Override
-    String chooseClientKeyIdentity(String identityHint, SSLEngine engine);
+    public String chooseClientKeyIdentity(String identityHint, SSLEngine engine) {
+        return "";
+    }
 
     /**
      * Gets the PSK to use for the provided socket.
      *
+     * <p>
+     * The default implementation returns {@code null}.
+     *
      * @param identityHint identity hint provided by the server to help select the key or
      *        {@code null} if none provided.
      * @param identity identity provided by the client to help select the key.
@@ -166,11 +193,16 @@
      *         the handshake.
      */
     @Override
-    SecretKey getKey(String identityHint, String identity, Socket socket);
+    public SecretKey getKey(String identityHint, String identity, Socket socket) {
+        return null;
+    }
 
     /**
      * Gets the PSK to use for the provided engine.
      *
+     * <p>
+     * The default implementation returns {@code null}.
+     *
      * @param identityHint identity hint provided by the server to help select the key or
      *        {@code null} if none provided.
      * @param identity identity provided by the client to help select the key.
@@ -179,5 +211,7 @@
      *         the handshake.
      */
     @Override
-    SecretKey getKey(String identityHint, String identity, SSLEngine engine);
+    public SecretKey getKey(String identityHint, String identity, SSLEngine engine) {
+        return null;
+    }
 }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 207dc4a..c1e6664 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,7 +19,6 @@
 
 import android.net.InterfaceConfiguration;
 import android.net.INetworkManagementEventObserver;
-import android.net.LinkAddress;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
 import android.net.UidRange;
@@ -313,11 +312,6 @@
      */
     void setDnsServersForNetwork(int netId, in String[] servers, String domains);
 
-    /**
-     * Flush the DNS cache associated with the specified network.
-     */
-    void flushNetworkDnsCache(int netId);
-
     void setFirewallEnabled(boolean enabled);
     boolean isFirewallEnabled();
     void setFirewallInterfaceRule(String iface, boolean allow);
@@ -336,17 +330,6 @@
     void removeVpnUidRanges(int netId, in UidRange[] ranges);
 
     /**
-     * Exempts {@code host} from the routing set up by {@link setMarkedForwardingRoute}
-     * All connects to {@code host} will use the global routing table
-     */
-    void setHostExemption(in LinkAddress host);
-
-    /**
-     * Clears an exemption set by {@link setHostExemption}
-     */
-    void clearHostExemption(in LinkAddress host);
-
-    /**
      * Start the clatd (464xlat) service
      */
     void startClatd(String interfaceName);
@@ -402,7 +385,6 @@
     void removeInterfaceFromNetwork(String iface, int netId);
 
     void addLegacyRouteForNetId(int netId, in RouteInfo routeInfo, int uid);
-    void removeLegacyRouteForNetId(int netId, in RouteInfo routeInfo, int uid);
 
     void setDefaultNetId(int netId);
     void clearDefaultNetId();
@@ -419,4 +401,7 @@
      * Deny UID from calling protect().
      */
     void denyProtect(int uid);
+
+    void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes);
+    void removeInterfaceFromLocalNetwork(String iface);
 }
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index b3705d8..19a8ef5 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -28,4 +28,5 @@
     void onNotificationRemoved(in StatusBarNotification notification,
             in NotificationRankingUpdate update);
     void onNotificationRankingUpdate(in NotificationRankingUpdate update);
+    void onListenerFlagsChanged(int flags);
 }
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 7d5ff33..1fc64e4 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -53,6 +53,12 @@
     private final String TAG = NotificationListenerService.class.getSimpleName()
             + "[" + getClass().getSimpleName() + "]";
 
+    /** {@link #getCurrentListenerFlags() Listener flags} constant - default state. **/
+    public static final int FLAG_NONE = 0;
+    /** {@link #getCurrentListenerFlags() Listener flags} constant - the primary device UI
+     * should disable notification sound, vibrating and other visual or aural effects. **/
+    public static final int FLAG_DISABLE_HOST_ALERTS = 1;
+
     private INotificationListenerWrapper mWrapper = null;
     private RankingMap mRankingMap;
 
@@ -156,6 +162,16 @@
         // optional
     }
 
+    /**
+     * Implement this method to be notified when the
+     * {@link #getCurrentListenerFlags() listener flags} change.
+     *
+     * @param flags The current {@link #getCurrentListenerFlags() listener flags}.
+     */
+    public void onListenerFlagsChanged(int flags) {
+        // optional
+    }
+
     private final INotificationManager getNotificationInterface() {
         if (mNoMan == null) {
             mNoMan = INotificationManager.Stub.asInterface(
@@ -279,6 +295,46 @@
     }
 
     /**
+     * Gets the set of flags representing current state.
+     *
+     * <p>
+     * The current state may differ from the requested state if the flag represents state
+     * shared across all listeners or a feature the notification host does not support or refuses
+     * to grant.
+     *
+     * @return One or more of the FLAG_ constants.
+     */
+    public final int getCurrentListenerFlags() {
+        if (!isBound()) return FLAG_NONE;
+        try {
+            return getNotificationInterface().getFlagsFromListener(mWrapper);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+            return FLAG_NONE;
+        }
+    }
+
+    /**
+     * Sets the desired {@link #getCurrentListenerFlags() listener flags}.
+     *
+     * <p>
+     * This is merely a request, the host may or not choose to take action depending
+     * on other listener requests or other global state.
+     * <p>
+     * Listen for updates using {@link #onListenerFlagsChanged(int)}.
+     *
+     * @param flags One or more of the FLAG_ constants.
+     */
+    public final void requestListenerFlags(int flags) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().requestFlagsFromListener(mWrapper, flags);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
      * Returns current ranking information.
      *
      * <p>
@@ -402,6 +458,14 @@
                 }
             }
         }
+        @Override
+        public void onListenerFlagsChanged(int flags) throws RemoteException {
+            try {
+                NotificationListenerService.this.onListenerFlagsChanged(flags);
+            } catch (Throwable t) {
+                Log.w(TAG, "Error running onListenerFlagsChanged", t);
+            }
+        }
     }
 
     private void applyUpdate(NotificationRankingUpdate update) {
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index e7cdc4e..e5a5292 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -30,6 +30,7 @@
     private final int id;
     private final String tag;
     private final String key;
+    private final String groupKey;
 
     private final int uid;
     private final String opPkg;
@@ -65,6 +66,7 @@
         this.notification.setUser(user);
         this.postTime = postTime;
         this.key = key();
+        this.groupKey = groupKey();
     }
 
     public StatusBarNotification(Parcel in) {
@@ -84,12 +86,26 @@
         this.notification.setUser(this.user);
         this.postTime = in.readLong();
         this.key = key();
+        this.groupKey = groupKey();
     }
 
     private String key() {
         return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
     }
 
+    private String groupKey() {
+        final String group = getNotification().getGroup();
+        final String sortKey = getNotification().getSortKey();
+        if (group == null && sortKey == null) {
+            // a group of one
+            return key;
+        }
+        return user.getIdentifier() + "|" + pkg + "|" +
+                (group == null
+                        ? "p:" + notification.priority
+                        : "g:" + group);
+    }
+
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(this.pkg);
         out.writeString(this.opPkg);
@@ -240,4 +256,11 @@
     public String getKey() {
         return key;
     }
+
+    /**
+     * A key that indicates the group with which this message ranks.
+     */
+    public String getGroupKey() {
+        return groupKey;
+    }
 }
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index ad30f44..d685cc5 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -27,6 +27,7 @@
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -41,26 +42,37 @@
  * always-on keyphrase detection APIs.
  */
 public class AlwaysOnHotwordDetector {
-    //---- States of Keyphrase availability ----//
+    //---- States of Keyphrase availability. Return codes for onAvailabilityChanged() ----//
     /**
-     * Indicates that the given keyphrase is not available on the system because of the
-     * hardware configuration.
+     * Indicates that this hotword detector is no longer valid for any recognition
+     * and should not be used anymore.
      */
-    public static final int KEYPHRASE_HARDWARE_UNAVAILABLE = -2;
+    public static final int STATE_INVALID = -3;
     /**
-     * Indicates that the given keyphrase is not supported.
+     * Indicates that recognition for the given keyphrase is not available on the system
+     * because of the hardware configuration.
      */
-    public static final int KEYPHRASE_UNSUPPORTED = -1;
+    public static final int STATE_HARDWARE_UNAVAILABLE = -2;
+    /**
+     * Indicates that recognition for the given keyphrase is not supported.
+     */
+    public static final int STATE_KEYPHRASE_UNSUPPORTED = -1;
     /**
      * Indicates that the given keyphrase is not enrolled.
      */
-    public static final int KEYPHRASE_UNENROLLED = 1;
+    public static final int STATE_KEYPHRASE_UNENROLLED = 1;
     /**
-     * Indicates that the given keyphrase is currently enrolled but not being actively listened for.
+     * Indicates that the given keyphrase is currently enrolled and it's possible to start
+     * recognition for it.
      */
-    public static final int KEYPHRASE_ENROLLED = 2;
+    public static final int STATE_KEYPHRASE_ENROLLED = 2;
 
-    // Keyphrase management actions ----//
+    /**
+     * Indicates that the detector isn't ready currently.
+     */
+    private static final int STATE_NOT_READY = 0;
+
+    // Keyphrase management actions. Used in getManageIntent() ----//
     /** Indicates that we need to enroll. */
     public static final int MANAGE_ACTION_ENROLL = 0;
     /** Indicates that we need to re-enroll. */
@@ -83,7 +95,7 @@
      */
     public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 0x1;
 
-    //---- Recognition mode flags ----//
+    //---- Recognition mode flags. Return codes for getSupportedRecognitionModes() ----//
     // Must be kept in sync with the related attribute defined as searchKeyphraseRecognitionFlags.
 
     /**
@@ -98,9 +110,12 @@
             = SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
 
     static final String TAG = "AlwaysOnHotwordDetector";
+    // TODO: Set to false.
+    static final boolean DBG = true;
 
-    private static final int MSG_HOTWORD_DETECTED = 1;
-    private static final int MSG_DETECTION_STOPPED = 2;
+    private static final int MSG_STATE_CHANGED = 1;
+    private static final int MSG_HOTWORD_DETECTED = 2;
+    private static final int MSG_DETECTION_STOPPED = 3;
 
     private final String mText;
     private final String mLocale;
@@ -109,23 +124,45 @@
      * This may be null if this keyphrase isn't supported by the enrollment application.
      */
     private final KeyphraseMetadata mKeyphraseMetadata;
-    /**
-     * The sound model for the keyphrase, derived from the model management service
-     * (IVoiceInteractionManagerService). May be null if the keyphrase isn't enrolled yet.
-     */
-    private final KeyphraseSoundModel mEnrolledSoundModel;
     private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
     private final IVoiceInteractionService mVoiceInteractionService;
     private final IVoiceInteractionManagerService mModelManagementService;
     private final SoundTriggerListener mInternalCallback;
     private final Callback mExternalCallback;
-    private final boolean mDisabled;
+    private final Object mLock = new Object();
+    private final Handler mHandler;
+
+    /**
+     * The sound model for the keyphrase, derived from the model management service
+     * (IVoiceInteractionManagerService). May be null if the keyphrase isn't enrolled yet.
+     */
+    private KeyphraseSoundModel mEnrolledSoundModel;
+    private int mAvailability = STATE_NOT_READY;
 
     /**
      * Callbacks for always-on hotword detection.
      */
     public interface Callback {
         /**
+         * Called when the hotword availability changes.
+         * This indicates a change in the availability of recognition for the given keyphrase.
+         * It's called at least once with the initial availability.<p/>
+         *
+         * Availability implies whether the hardware on this system is capable of listening for
+         * the given keyphrase or not. <p/>
+         * If the return code is one of {@link #STATE_HARDWARE_UNAVAILABLE} or
+         * {@link #STATE_KEYPHRASE_UNSUPPORTED},
+         * detection is not possible and no further interaction should be
+         * performed with this detector. <br/>
+         * If it is {@link #STATE_KEYPHRASE_UNENROLLED} the caller may choose to begin
+         * an enrollment flow for the keyphrase. <br/>
+         * and for {@link #STATE_KEYPHRASE_ENROLLED} a recognition can be started as desired. <p/>
+         *
+         * If the return code is {@link #STATE_INVALID}, this detector is stale.
+         * A new detector should be obtained for use in the future.
+         */
+        void onAvailabilityChanged(int status);
+        /**
          * Called when the keyphrase is spoken.
          *
          * @param data Optional trigger audio data, if it was requested during
@@ -156,51 +193,30 @@
         mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
         mKeyphraseMetadata = mKeyphraseEnrollmentInfo.getKeyphraseMetadata(text, locale);
         mExternalCallback = callback;
-        mInternalCallback = new SoundTriggerListener(new MyHandler());
+        mHandler = new MyHandler();
+        mInternalCallback = new SoundTriggerListener(mHandler);
         mVoiceInteractionService = voiceInteractionService;
         mModelManagementService = modelManagementService;
-        if (mKeyphraseMetadata != null) {
-            mEnrolledSoundModel = internalGetKeyphraseSoundModel(mKeyphraseMetadata.id);
-        } else {
-            mEnrolledSoundModel = null;
-        }
-        int initialAvailability = internalGetAvailabilityLocked();
-        mDisabled = (initialAvailability == KEYPHRASE_HARDWARE_UNAVAILABLE)
-                || (initialAvailability == KEYPHRASE_UNSUPPORTED);
-    }
-
-    /**
-     * Gets the state of always-on hotword detection for the given keyphrase and locale
-     * on this system.
-     * Availability implies that the hardware on this system is capable of listening for
-     * the given keyphrase or not.
-     *
-     * @return Indicates if always-on hotword detection is available for the given keyphrase.
-     *         The return code is one of {@link #KEYPHRASE_HARDWARE_UNAVAILABLE},
-     *         {@link #KEYPHRASE_UNSUPPORTED}, {@link #KEYPHRASE_UNENROLLED} or
-     *         {@link #KEYPHRASE_ENROLLED}.
-     */
-    public int getAvailability() {
-        synchronized (this) {
-            return internalGetAvailabilityLocked();
-        }
+        new RefreshAvailabiltyTask().execute();
     }
 
     /**
      * Gets the recognition modes supported by the associated keyphrase.
      *
      * @throws UnsupportedOperationException if the keyphrase itself isn't supported.
-     *         Callers should check the availability by calling {@link #getAvailability()}
-     *         before calling this method to avoid this exception.
+     *         Callers should only call this method after a supported state callback on
+     *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
      */
     public int getSupportedRecognitionModes() {
-        synchronized (this) {
+        synchronized (mLock) {
             return getSupportedRecognitionModesLocked();
         }
     }
 
     private int getSupportedRecognitionModesLocked() {
-        if (mDisabled) {
+        // This method only makes sense if we can actually support a recognition.
+        if (mAvailability != STATE_KEYPHRASE_ENROLLED
+                && mAvailability != STATE_KEYPHRASE_UNENROLLED) {
             throw new UnsupportedOperationException(
                     "Getting supported recognition modes for the keyphrase is not supported");
         }
@@ -216,17 +232,18 @@
      *        {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO}.
      * @return {@link #STATUS_OK} if the call succeeds, an error code otherwise.
      * @throws UnsupportedOperationException if the recognition isn't supported.
-     *         Callers should check the availability by calling {@link #getAvailability()}
-     *         before calling this method to avoid this exception.
+     *         Callers should only call this method after a supported state callback on
+     *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
      */
     public int startRecognition(int recognitionFlags) {
-        synchronized (this) {
+        synchronized (mLock) {
             return startRecognitionLocked(recognitionFlags);
         }
     }
 
     private int startRecognitionLocked(int recognitionFlags) {
-        if (internalGetAvailabilityLocked() != KEYPHRASE_ENROLLED) {
+        // This method only makes sense if we can start a recognition.
+        if (mAvailability != STATE_KEYPHRASE_ENROLLED) {
             throw new UnsupportedOperationException(
                     "Recognition for the given keyphrase is not supported");
         }
@@ -257,17 +274,18 @@
      *
      * @return {@link #STATUS_OK} if the call succeeds, an error code otherwise.
      * @throws UnsupportedOperationException if the recognition isn't supported.
-     *         Callers should check the availability by calling {@link #getAvailability()}
-     *         before calling this method to avoid this exception.
+     *         Callers should only call this method after a supported state callback on
+     *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
      */
     public int stopRecognition() {
-        synchronized (this) {
+        synchronized (mLock) {
             return stopRecognitionLocked();
         }
     }
 
-    private synchronized int stopRecognitionLocked() {
-        if (internalGetAvailabilityLocked() != KEYPHRASE_ENROLLED) {
+    private int stopRecognitionLocked() {
+        // This method only makes sense if we can start a recognition.
+        if (mAvailability != STATE_KEYPHRASE_ENROLLED) {
             throw new UnsupportedOperationException(
                     "Recognition for the given keyphrase is not supported");
         }
@@ -294,11 +312,13 @@
      *        {@link #MANAGE_ACTION_UN_ENROLL}.
      * @return An {@link Intent} to manage the given keyphrase.
      * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
-     *         Callers should check the availability by calling {@link #getAvailability()}
-     *         before calling this method to avoid this exception.
+     *         Callers should only call this method after a supported state callback on
+     *         {@link Callback#onAvailabilityChanged(int)} to avoid this exception.
      */
     public Intent getManageIntent(int action) {
-        if (mDisabled) {
+        // This method only makes sense if we can actually support a recognition.
+        if (mAvailability != STATE_KEYPHRASE_ENROLLED
+                && mAvailability != STATE_KEYPHRASE_UNENROLLED) {
             throw new UnsupportedOperationException(
                     "Managing the given keyphrase is not supported");
         }
@@ -311,55 +331,44 @@
         return mKeyphraseEnrollmentInfo.getManageKeyphraseIntent(action, mText, mLocale);
     }
 
-    private int internalGetAvailabilityLocked() {
-        ModuleProperties dspModuleProperties = null;
-        try {
-            dspModuleProperties =
-                    mModelManagementService.getDspModuleProperties(mVoiceInteractionService);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "RemoteException in getDspProperties!");
+    /**
+     * Invalidates this hotword detector so that any future calls to this result
+     * in an IllegalStateException.
+     *
+     * @hide
+     */
+    void invalidate() {
+        synchronized (mLock) {
+            mAvailability = STATE_INVALID;
+            notifyStateChangedLocked();
         }
-        // No DSP available
-        if (dspModuleProperties == null) {
-            return KEYPHRASE_HARDWARE_UNAVAILABLE;
-        }
-        // No enrollment application supports this keyphrase/locale
-        if (mKeyphraseMetadata == null) {
-            return KEYPHRASE_UNSUPPORTED;
-        }
-        // This keyphrase hasn't been enrolled.
-        if (mEnrolledSoundModel == null) {
-            return KEYPHRASE_UNENROLLED;
-        }
-        return KEYPHRASE_ENROLLED;
     }
 
     /**
-     * @return The corresponding {@link KeyphraseSoundModel} or null if none is found.
+     * Reloads the sound models from the service.
+     *
+     * @hide
      */
-    private KeyphraseSoundModel internalGetKeyphraseSoundModel(int keyphraseId) {
-        List<KeyphraseSoundModel> soundModels;
-        try {
-            soundModels = mModelManagementService
-                    .listRegisteredKeyphraseSoundModels(mVoiceInteractionService);
-            if (soundModels == null || soundModels.isEmpty()) {
-                Slog.i(TAG, "No available sound models for keyphrase ID: " + keyphraseId);
-                return null;
+    void onSoundModelsChanged() {
+        synchronized (mLock) {
+            // TODO: This should stop the recognition if it was using an enrolled sound model
+            // that's no longer available.
+            if (mAvailability == STATE_INVALID
+                    || mAvailability == STATE_HARDWARE_UNAVAILABLE
+                    || mAvailability == STATE_KEYPHRASE_UNSUPPORTED) {
+                Slog.w(TAG, "Received onSoundModelsChanged for an unsupported keyphrase/config");
+                return;
             }
-            for (KeyphraseSoundModel soundModel : soundModels) {
-                if (soundModel.keyphrases == null) {
-                    continue;
-                }
-                for (Keyphrase keyphrase : soundModel.keyphrases) {
-                    if (keyphrase.id == keyphraseId) {
-                        return soundModel;
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            Slog.w(TAG, "RemoteException in listRegisteredKeyphraseSoundModels!");
+
+            // Execute a refresh availability task - which should then notify of a change.
+            new RefreshAvailabiltyTask().execute();
         }
-        return null;
+    }
+
+    private void notifyStateChangedLocked() {
+        Message message = Message.obtain(mHandler, MSG_STATE_CHANGED);
+        message.arg1 = mAvailability;
+        message.sendToTarget();
     }
 
     /** @hide */
@@ -389,6 +398,9 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
+                case MSG_STATE_CHANGED:
+                    mExternalCallback.onAvailabilityChanged(msg.arg1);
+                    break;
                 case MSG_HOTWORD_DETECTED:
                     mExternalCallback.onDetected((byte[]) msg.obj);
                     break;
@@ -399,4 +411,95 @@
             }
         }
     }
+
+    class RefreshAvailabiltyTask extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        public Void doInBackground(Void... params) {
+            int availability = internalGetInitialAvailability();
+            KeyphraseSoundModel soundModel = null;
+            // Fetch the sound model if the availability is one of the supported ones.
+            if (availability == STATE_NOT_READY
+                    || availability == STATE_KEYPHRASE_UNENROLLED
+                    || availability == STATE_KEYPHRASE_ENROLLED) {
+                soundModel =
+                        internalGetKeyphraseSoundModel(mKeyphraseMetadata.id);
+                if (soundModel == null) {
+                    availability = STATE_KEYPHRASE_UNENROLLED;
+                } else {
+                    availability = STATE_KEYPHRASE_ENROLLED;
+                }
+            }
+
+            synchronized (mLock) {
+                if (DBG) {
+                    Slog.d(TAG, "Hotword availability changed from " + mAvailability
+                            + " -> " + availability);
+                }
+                mAvailability = availability;
+                mEnrolledSoundModel = soundModel;
+                notifyStateChangedLocked();
+            }
+            return null;
+        }
+
+        /**
+         * @return The initial availability without checking the enrollment status.
+         */
+        private int internalGetInitialAvailability() {
+            synchronized (mLock) {
+                // This detector has already been invalidated.
+                if (mAvailability == STATE_INVALID) {
+                    return STATE_INVALID;
+                }
+            }
+
+            ModuleProperties dspModuleProperties = null;
+            try {
+                dspModuleProperties =
+                        mModelManagementService.getDspModuleProperties(mVoiceInteractionService);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "RemoteException in getDspProperties!");
+            }
+            // No DSP available
+            if (dspModuleProperties == null) {
+                return STATE_HARDWARE_UNAVAILABLE;
+            }
+            // No enrollment application supports this keyphrase/locale
+            if (mKeyphraseMetadata == null) {
+                return STATE_KEYPHRASE_UNSUPPORTED;
+            }
+            return STATE_NOT_READY;
+        }
+
+        /**
+         * @return The corresponding {@link KeyphraseSoundModel} or null if none is found.
+         */
+        private KeyphraseSoundModel internalGetKeyphraseSoundModel(int keyphraseId) {
+            List<KeyphraseSoundModel> soundModels;
+            try {
+                soundModels = mModelManagementService
+                        .listRegisteredKeyphraseSoundModels(mVoiceInteractionService);
+                if (soundModels == null || soundModels.isEmpty()) {
+                    Slog.i(TAG, "No available sound models for keyphrase ID: " + keyphraseId);
+                    return null;
+                }
+                for (int i = 0; i < soundModels.size(); i++) {
+                    KeyphraseSoundModel soundModel = soundModels.get(i);
+                    if (soundModel.keyphrases == null || soundModel.keyphrases.length == 0) {
+                        continue;
+                    }
+                    for (int j = 0; i < soundModel.keyphrases.length; j++) {
+                        Keyphrase keyphrase = soundModel.keyphrases[j];
+                        if (keyphrase.id == keyphraseId) {
+                            return soundModel;
+                        }
+                    }
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "RemoteException in listRegisteredKeyphraseSoundModels!");
+            }
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl
index c9915a2..e8265a2 100644
--- a/core/java/android/service/voice/IVoiceInteractionService.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionService.aidl
@@ -21,4 +21,6 @@
  */
 oneway interface IVoiceInteractionService {
     void ready();
+    void soundModelsChanged();
+    void shutdown();
 }
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 982f43d..82e23c4 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -28,8 +28,8 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-
 import android.provider.Settings;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IVoiceInteractionManagerService;
 
@@ -70,15 +70,27 @@
         @Override public void ready() {
             mHandler.sendEmptyMessage(MSG_READY);
         }
+        @Override public void shutdown() {
+            mHandler.sendEmptyMessage(MSG_SHUTDOWN);
+        }
+        @Override public void soundModelsChanged() {
+            mHandler.sendEmptyMessage(MSG_SOUND_MODELS_CHANGED);
+        }
     };
 
     MyHandler mHandler;
 
     IVoiceInteractionManagerService mSystemService;
 
+    private final Object mLock = new Object();
+
     private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
 
+    private AlwaysOnHotwordDetector mHotwordDetector;
+
     static final int MSG_READY = 1;
+    static final int MSG_SHUTDOWN = 2;
+    static final int MSG_SOUND_MODELS_CHANGED = 3;
 
     class MyHandler extends Handler {
         @Override
@@ -87,6 +99,12 @@
                 case MSG_READY:
                     onReady();
                     break;
+                case MSG_SHUTDOWN:
+                    onShutdownInternal();
+                    break;
+                case MSG_SOUND_MODELS_CHANGED:
+                    onSoundModelsChangedInternal();
+                    break;
                 default:
                     super.handleMessage(msg);
             }
@@ -140,9 +158,10 @@
 
     /**
      * Called during service initialization to tell you when the system is ready
-     * to receive interaction from it.  You should generally do initialization here
-     * rather than in {@link #onCreate()}.  Methods such as {@link #startSession}
-     * and {@link #getAlwaysOnHotwordDetector} will not be operational until this point.
+     * to receive interaction from it. You should generally do initialization here
+     * rather than in {@link #onCreate()}. Methods such as {@link #startSession(Bundle)} and
+     * {@link #createAlwaysOnHotwordDetector(String, String, android.service.voice.AlwaysOnHotwordDetector.Callback)}
+     * will not be operational until this point.
      */
     public void onReady() {
         mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
@@ -150,22 +169,56 @@
         mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager());
     }
 
+    private void onShutdownInternal() {
+        onShutdown();
+        // Stop any active recognitions when shutting down.
+        // This ensures that if implementations forget to stop any active recognition,
+        // It's still guaranteed to have been stopped.
+        // This helps with cases where the voice interaction implementation is changed
+        // by the user.
+        safelyShutdownHotwordDetector();
+    }
+
     /**
+     * Called during service de-initialization to tell you when the system is shutting the
+     * service down.
+     */
+    public void onShutdown() {
+    }
+
+    private void onSoundModelsChangedInternal() {
+        synchronized (this) {
+            if (mHotwordDetector != null) {
+                // TODO: Stop recognition if a sound model that was being recognized gets deleted.
+                mHotwordDetector.onSoundModelsChanged();
+            }
+        }
+    }
+
+    /**
+     * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale.
+     * This instance must be retained and used by the client.
+     * Calling this a second time invalidates the previously created hotword detector
+     * which can no longer be used to manage recognition.
+     *
      * @param keyphrase The keyphrase that's being used, for example "Hello Android".
      * @param locale The locale for which the enrollment needs to be performed.
      *        This is a Java locale, for example "en_US".
      * @param callback The callback to notify of detection events.
      * @return An always-on hotword detector for the given keyphrase and locale.
      */
-    public final AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(
+    public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(
             String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) {
         if (mSystemService == null) {
             throw new IllegalStateException("Not available until onReady() is called");
         }
-        // TODO: Cache instances and return the same one instead of creating a new interactor
-        // for the same keyphrase/locale combination.
-        return new AlwaysOnHotwordDetector(keyphrase, locale, callback,
-                mKeyphraseEnrollmentInfo, mInterface, mSystemService);
+        synchronized (mLock) {
+            // Allow only one concurrent recognition via the APIs.
+            safelyShutdownHotwordDetector();
+            mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback,
+                    mKeyphraseEnrollmentInfo, mInterface, mSystemService);
+        }
+        return mHotwordDetector;
     }
 
     /**
@@ -176,4 +229,18 @@
     protected final KeyphraseEnrollmentInfo getKeyphraseEnrollmentInfo() {
         return mKeyphraseEnrollmentInfo;
     }
+
+    private void safelyShutdownHotwordDetector() {
+        try {
+            synchronized (mLock) {
+                if (mHotwordDetector != null) {
+                    mHotwordDetector.stopRecognition();
+                    mHotwordDetector.invalidate();
+                    mHotwordDetector = null;
+                }
+            }
+        } catch (Exception ex) {
+            // Ignore.
+        }
+    }
 }
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index 3f5e8e8..1550297 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -193,7 +193,8 @@
                         bottomRightAnimator = ObjectAnimator.ofInt(view, "right", "bottom",
                                 bottomRightPath);
                     }
-                    Animator anim = mergeAnimators(topLeftAnimator, bottomRightAnimator);
+                    Animator anim = TransitionUtils.mergeAnimators(topLeftAnimator,
+                            bottomRightAnimator);
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         parent.suppressLayout(true);
@@ -256,7 +257,8 @@
                         clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator,
                                 tempStartBounds, tempEndBounds);
                     }
-                    Animator anim = mergeAnimators(translationAnimator, clipAnimator);
+                    Animator anim = TransitionUtils.mergeAnimators(translationAnimator,
+                            clipAnimator);
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         parent.suppressLayout(true);
@@ -330,16 +332,4 @@
         }
         return null;
     }
-
-    private static Animator mergeAnimators(Animator animator1, Animator animator2) {
-        if (animator1 == null) {
-            return animator2;
-        } else if (animator2 == null) {
-            return animator1;
-        } else {
-            AnimatorSet animatorSet = new AnimatorSet();
-            animatorSet.playTogether(animator1, animator2);
-            return animatorSet;
-        }
-    }
 }
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 12437d7..2b26756 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -32,10 +32,12 @@
 import java.util.Map;
 
 /**
- * Transitions changes in ImageView {@link ImageView#setScaleType(ImageView.ScaleType)} as
- * well as image scaling due to ImageView size changes. When combined with
- * {@link android.transition.ChangeBounds}, an ImageView that changes size will
- * scale smoothly.
+ * This Transition captures an ImageView's matrix before and after the
+ * scene change and animates it during the transition.
+ *
+ * <p>In combination with ChangeBounds, ChangeImageTransform allows ImageViews
+ * that change size, shape, or {@link android.widget.ImageView.ScaleType} to animate contents
+ * smoothly.</p>
  */
 public class ChangeImageTransform extends Transition {
 
@@ -192,30 +194,8 @@
 
     private ObjectAnimator createMatrixAnimator(final ImageView imageView, Matrix startMatrix,
             final Matrix endMatrix) {
-        ObjectAnimator animator = ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
+        return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
                 new MatrixEvaluator(), startMatrix, endMatrix);
-        /*
-        AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
-            private Matrix mPausedMatrix;
-
-            @Override
-            public void onAnimationPause(Animator animation) {
-                if (mPausedMatrix == null) {
-                    mPausedMatrix = new Matrix();
-                }
-                Matrix imageMatrix = imageView.getImageMatrix();
-                mPausedMatrix.set(imageMatrix);
-                imageView.animateTransform(endMatrix);
-            }
-
-            @Override
-            public void onAnimationResume(Animator animation) {
-                imageView.animateTransform(mPausedMatrix);
-            }
-        };
-        animator.addPauseListener(listener);
-        */
-        return animator;
     }
 
     private static class MatrixEvaluator implements TypeEvaluator<Matrix> {
diff --git a/core/java/android/transition/ChangeScroll.java b/core/java/android/transition/ChangeScroll.java
new file mode 100644
index 0000000..39291bf
--- /dev/null
+++ b/core/java/android/transition/ChangeScroll.java
@@ -0,0 +1,83 @@
+/*
+ * 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.transition;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * This transition captures the scroll properties of targets before and after
+ * the scene change and animates any changes.
+ *
+ * @hide
+ */
+public class ChangeScroll extends Transition {
+
+    private static final String PROPNAME_SCROLL_X = "android:changeScroll:x";
+    private static final String PROPNAME_SCROLL_Y = "android:changeScroll:y";
+
+    public ChangeScroll() {}
+
+    public ChangeScroll(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    private void captureValues(TransitionValues transitionValues) {
+        transitionValues.values.put(PROPNAME_SCROLL_X, transitionValues.view.getScrollX());
+        transitionValues.values.put(PROPNAME_SCROLL_Y, transitionValues.view.getScrollY());
+    }
+
+    @Override
+    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        if (startValues == null || endValues == null) {
+            return null;
+        }
+        final View view = endValues.view;
+        int startX = (Integer) startValues.values.get(PROPNAME_SCROLL_X);
+        int endX = (Integer) endValues.values.get(PROPNAME_SCROLL_X);
+        int startY = (Integer) startValues.values.get(PROPNAME_SCROLL_Y);
+        int endY = (Integer) endValues.values.get(PROPNAME_SCROLL_Y);
+        Animator scrollXAnimator = null;
+        Animator scrollYAnimator = null;
+        if (startX != endX) {
+            view.setScrollX(startX);
+            scrollXAnimator = ObjectAnimator.ofInt(view, "scrollX", startX, endX);
+        }
+        if (startY != endY) {
+            view.setScrollY(startY);
+            scrollYAnimator = ObjectAnimator.ofInt(view, "scrollY", startY, endY);
+        }
+        return TransitionUtils.mergeAnimators(scrollXAnimator, scrollYAnimator);
+    }
+}
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 420c248..1f9d093 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -69,17 +69,17 @@
      * Fading mode used in {@link #Fade(int)} to make the transition
      * operate on targets that are appearing. Maybe be combined with
      * {@link #OUT} to fade both in and out. Equivalent to
-     * {@link Visibility#IN}.
+     * {@link Visibility#MODE_IN}.
      */
-    public static final int IN = Visibility.IN;
+    public static final int IN = Visibility.MODE_IN;
 
     /**
      * Fading mode used in {@link #Fade(int)} to make the transition
      * operate on targets that are disappearing. Maybe be combined with
      * {@link #IN} to fade both in and out. Equivalent to
-     * {@link Visibility#OUT}.
+     * {@link Visibility#MODE_OUT}.
      */
-    public static final int OUT = Visibility.OUT;
+    public static final int OUT = Visibility.MODE_OUT;
 
     /**
      * Constructs a Fade transition that will fade targets in and out.
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 68b0a43..760ffe1 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -159,6 +159,8 @@
                 transition = new AutoTransition(mContext, attrs);
             } else if ("recolor".equals(name)) {
                 transition = new Recolor(mContext, attrs);
+            } else if ("changeScroll".equals(name)) {
+                transition = new ChangeScroll(mContext, attrs);
             } else if ("transitionSet".equals(name)) {
                 transition = new TransitionSet(mContext, attrs);
             } else if ("transition".equals(name)) {
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
new file mode 100644
index 0000000..931d46a
--- /dev/null
+++ b/core/java/android/transition/TransitionUtils.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 android.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+
+/**
+ * Static utility methods for Transitions.
+ *
+ * @hide
+ */
+public class TransitionUtils {
+
+    static Animator mergeAnimators(Animator animator1, Animator animator2) {
+        if (animator1 == null) {
+            return animator2;
+        } else if (animator2 == null) {
+            return animator1;
+        } else {
+            AnimatorSet animatorSet = new AnimatorSet();
+            animatorSet.playTogether(animator1, animator2);
+            return animatorSet;
+        }
+    }
+}
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index cf5ea4c..af2016c 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -50,16 +50,16 @@
     /**
      * Mode used in {@link #setMode(int)} to make the transition
      * operate on targets that are appearing. Maybe be combined with
-     * {@link #OUT} to target Visibility changes both in and out.
+     * {@link #MODE_OUT} to target Visibility changes both in and out.
      */
-    public static final int IN = 0x1;
+    public static final int MODE_IN = 0x1;
 
     /**
      * Mode used in {@link #setMode(int)} to make the transition
      * operate on targets that are disappearing. Maybe be combined with
-     * {@link #IN} to target Visibility changes both in and out.
+     * {@link #MODE_IN} to target Visibility changes both in and out.
      */
-    public static final int OUT = 0x2;
+    public static final int MODE_OUT = 0x2;
 
     private static final String[] sTransitionProperties = {
             PROPNAME_VISIBILITY,
@@ -76,7 +76,7 @@
         ViewGroup endParent;
     }
 
-    private int mMode = IN | OUT;
+    private int mMode = MODE_IN | MODE_OUT;
 
     private int mForcedStartVisibility = -1;
     private int mForcedEndVisibility = -1;
@@ -98,12 +98,12 @@
      * on <code>mode</code>.
      *
      * @param mode The behavior supported by this transition, a combination of
-     *             {@link #IN} and {@link #OUT}.
+     *             {@link #MODE_IN} and {@link #MODE_OUT}.
      * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
      */
     public void setMode(int mode) {
-        if ((mode & ~(IN | OUT)) != 0) {
-            throw new IllegalArgumentException("Only IN and OUT flags are allowed");
+        if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
+            throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
         }
         mMode = mode;
     }
@@ -112,7 +112,7 @@
      * Returns whether appearing and/or disappearing Views are supported.
      *
      * Returns whether appearing and/or disappearing Views are supported. A combination of
-     *         {@link #IN} and {@link #OUT}.
+     *         {@link #MODE_IN} and {@link #MODE_OUT}.
      * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
      */
     public int getMode() {
@@ -276,7 +276,7 @@
     public Animator onAppear(ViewGroup sceneRoot,
             TransitionValues startValues, int startVisibility,
             TransitionValues endValues, int endVisibility) {
-        if ((mMode & IN) != IN || endValues == null) {
+        if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
             return null;
         }
         return onAppear(sceneRoot, endValues.view, startValues, endValues);
@@ -339,7 +339,7 @@
     public Animator onDisappear(ViewGroup sceneRoot,
             TransitionValues startValues, int startVisibility,
             TransitionValues endValues, int endVisibility) {
-        if ((mMode & OUT) != OUT) {
+        if ((mMode & MODE_OUT) != MODE_OUT) {
             return null;
         }
 
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 0a1204d..73c73218 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -346,7 +346,9 @@
      * Deep copies the data into native to simplify reference ownership.
      */
     public boolean setOutline(Outline outline) {
-        if (outline == null || outline.isEmpty()) {
+        if (outline == null) {
+            return nSetOutlineNone(mNativeRenderNode);
+        } else if (outline.isEmpty()) {
             return nSetOutlineEmpty(mNativeRenderNode);
         } else if (outline.mRect != null) {
             return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
@@ -878,6 +880,7 @@
             int right, int bottom, float radius);
     private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath);
     private static native boolean nSetOutlineEmpty(long renderNode);
+    private static native boolean nSetOutlineNone(long renderNode);
     private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
     private static native boolean nSetRevealClip(long renderNode,
             boolean shouldClip, boolean inverseClip, float x, float y, float radius);
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 64d03be..71102e8 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -233,10 +233,11 @@
         if (!TextUtils.isEmpty(subtitle)) {
             setSubtitle(subtitle);
         }
-        a.recycle();
 
-        mPopupContext = context;
-        mPopupTheme = 0;
+        // Set the default context, since setPopupTheme() may be a no-op.
+        mPopupContext = mContext;
+        setPopupTheme(a.getResourceId(R.styleable.Toolbar_popupTheme, 0));
+        a.recycle();
     }
 
     /**
diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
index 5ab9217..6ed3bdc 100644
--- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
+++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
@@ -58,7 +58,6 @@
         Log.d("ExternalMediaFormatActivity", "onCreate!");
         // Set up the "dialog"
         final AlertController.AlertParams p = mAlertParams;
-        p.mIconId = com.android.internal.R.drawable.stat_sys_warning;
         p.mTitle = getString(com.android.internal.R.string.extmedia_format_title);
         p.mMessage = getString(com.android.internal.R.string.extmedia_format_message);
         p.mPositiveButtonText = getString(com.android.internal.R.string.extmedia_format_button_format);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 901d6e6..d91eb69 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -27,6 +27,10 @@
     // be kept in sync with frameworks/native/include/binder/IBatteryStats.h
     void noteStartSensor(int uid, int sensor);
     void noteStopSensor(int uid, int sensor);
+    void noteStartVideo(int uid);
+    void noteStopVideo(int uid);
+    void noteStartAudio(int uid);
+    void noteStopAudio(int uid);
 
     // Remaining methods are only used in Java.
     byte[] getStatistics();
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index a866ca7..229df8f 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -36,7 +36,6 @@
 import android.widget.TextView;
 
 import java.text.Collator;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
@@ -106,22 +105,21 @@
         return constructAdapter(context, layoutId, fieldId, false /* disable pseudolocales */);
     }
 
-    public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
-            final int layoutId, final int fieldId, final boolean isInDeveloperMode) {
+    public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
         final Resources resources = context.getResources();
 
-        String[] locales = Resources.getSystem().getAssets().getLocales();
+        final String[] locales = Resources.getSystem().getAssets().getLocales();
         List<String> localeList = new ArrayList<String>(locales.length);
         Collections.addAll(localeList, locales);
         if (isInDeveloperMode) {
             if (!localeList.contains("zz_ZZ")) {
                 localeList.add("zz_ZZ");
             }
-        /** - TODO: Enable when zz_ZY Pseudolocale is complete
-         *  if (!localeList.contains("zz_ZY")) {
-         *      localeList.add("zz_ZY");
-         *  }
-         */
+            /** - TODO: Enable when zz_ZY Pseudolocale is complete
+             *  if (!localeList.contains("zz_ZY")) {
+             *      localeList.add("zz_ZY");
+             *	}
+             */
         }
 
         Collections.sort(localeList);
@@ -179,6 +177,13 @@
         }
 
         Collections.sort(localeInfos);
+        return localeInfos;
+    }
+
+    public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
+            final int layoutId, final int fieldId, final boolean isInDeveloperMode) {
+        final List<LocaleInfo> localeInfos = getAllAssetLocales(context, isInDeveloperMode);
+
         final LayoutInflater inflater =
                 (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos) {
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index e1166f1..b951f50e 100644
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -87,7 +87,6 @@
         final Intent intent = getIntent();
         final AlertController.AlertParams p = mAlertParams;
         Context context = getApplicationContext();
-        p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
         p.mTitle = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TITLE);
         p.mMessage = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_MESSAGE);
         p.mPositiveButtonText = String.format(context.getString(R.string.gpsVerifYes));
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index e1a4909..5da5ae9 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -27,6 +27,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -154,6 +156,11 @@
                 mToolbar.setSubtitleTextAppearance(mToolbar.getContext(), subtitleTextStyle);
             }
 
+            final int popupTheme = a.getResourceId(R.styleable.ActionBar_popupTheme, 0);
+            if (popupTheme != 0) {
+                mToolbar.setPopupTheme(popupTheme);
+            }
+
             a.recycle();
         }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f65aab5..7b5395b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -113,6 +113,7 @@
 	android/graphics/NinePatchImpl.cpp \
 	android/graphics/NinePatchPeeker.cpp \
 	android/graphics/Paint.cpp \
+	android/graphics/PaintImpl.cpp \
 	android/graphics/Path.cpp \
 	android/graphics/PathMeasure.cpp \
 	android/graphics/PathEffect.cpp \
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
old mode 100644
new mode 100755
index 53aca3d..70cf9a8
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1,3 +1,4 @@
+#include "Paint.h"
 #include "SkBitmap.h"
 #include "SkPixelRef.h"
 #include "SkImageEncoder.h"
@@ -676,7 +677,7 @@
                                    jlong srcHandle, jlong paintHandle,
                                    jintArray offsetXY) {
     const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
     SkIPoint  offset;
     SkBitmap* dst = new SkBitmap;
     JavaPixelAllocator allocator(env);
@@ -845,7 +846,19 @@
     const int h = bm0->height();
     const size_t size = bm0->width() * bm0->bytesPerPixel();
     for (int y = 0; y < h; y++) {
-        if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
+        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
+        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
+        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
+        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
+        // to warn user those 2 unrecognized config bitmaps may be different.
+        void *bm0Addr = bm0->getAddr(0, y);
+        void *bm1Addr = bm1->getAddr(0, y);
+
+        if(bm0Addr == NULL || bm1Addr == NULL) {
+            return JNI_FALSE;
+        }
+
+        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
             return JNI_FALSE;
         }
     }
diff --git a/core/jni/android/graphics/Canvas.h b/core/jni/android/graphics/Canvas.h
index fde22ee..317f69d 100644
--- a/core/jni/android/graphics/Canvas.h
+++ b/core/jni/android/graphics/Canvas.h
@@ -25,6 +25,7 @@
 
 // TODO: move this further up the stack so that all interaction with minikin
 //       happens prior to calling into this interface
+class Paint;
 class TypefaceImpl;
 
 class Canvas {
@@ -60,7 +61,7 @@
     virtual void restoreToCount(int saveCount) = 0;
 
     virtual int saveLayer(float left, float top, float right, float bottom,
-                const SkPaint* paint, SkCanvas::SaveFlags flags) = 0;
+                const Paint* paint, SkCanvas::SaveFlags flags) = 0;
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
             int alpha, SkCanvas::SaveFlags flags) = 0;
 
@@ -90,47 +91,47 @@
 // Canvas draw operations
 // ----------------------------------------------------------------------------
     virtual void drawColor(int color, SkXfermode::Mode mode) = 0;
-    virtual void drawPaint(const SkPaint& paint) = 0;
+    virtual void drawPaint(const Paint& paint) = 0;
 
     // Geometry
-    virtual void drawPoint(float x, float y, const SkPaint& paint) = 0;
-    virtual void drawPoints(const float* points, int count, const SkPaint& paint) = 0;
+    virtual void drawPoint(float x, float y, const Paint& paint) = 0;
+    virtual void drawPoints(const float* points, int count, const Paint& paint) = 0;
     virtual void drawLine(float startX, float startY, float stopX, float stopY,
-                const SkPaint& paint) = 0;
-    virtual void drawLines(const float* points, int count, const SkPaint& paint) = 0;
+                const Paint& paint) = 0;
+    virtual void drawLines(const float* points, int count, const Paint& paint) = 0;
     virtual void drawRect(float left, float top, float right, float bottom,
-            const SkPaint& paint) = 0;
+            const Paint& paint) = 0;
     virtual void drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, const SkPaint& paint) = 0;
-    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) = 0;
+            float rx, float ry, const Paint& paint) = 0;
+    virtual void drawCircle(float x, float y, float radius, const Paint& paint) = 0;
     virtual void drawOval(float left, float top, float right, float bottom,
-            const SkPaint& paint) = 0;
+            const Paint& paint) = 0;
     virtual void drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) = 0;
-    virtual void drawPath(const SkPath& path, const SkPaint& paint) = 0;
+            float startAngle, float sweepAngle, bool useCenter, const Paint& paint) = 0;
+    virtual void drawPath(const SkPath& path, const Paint& paint) = 0;
     virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
                               const float* verts, const float* tex, const int* colors,
-                              const uint16_t* indices, int indexCount, const SkPaint& paint) = 0;
+                              const uint16_t* indices, int indexCount, const Paint& paint) = 0;
 
     // Bitmap-based
     virtual void drawBitmap(const SkBitmap& bitmap, float left, float top,
-            const SkPaint* paint) = 0;
+            const Paint* paint) = 0;
     virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
-            const SkPaint* paint) = 0;
+            const Paint* paint) = 0;
     virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, const SkPaint* paint) = 0;
+            float dstRight, float dstBottom, const Paint* paint) = 0;
     virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
-            const float* vertices, const int* colors, const SkPaint* paint) = 0;
+            const float* vertices, const int* colors, const Paint* paint) = 0;
 
     // Text
     virtual void drawText(const uint16_t* text, int start, int count, int contextCount,
-            float x, float y, int bidiFlags, const SkPaint& paint,
+            float x, float y, int bidiFlags, const Paint& paint,
             TypefaceImpl* typeface) = 0;
     virtual void drawPosText(const uint16_t* text, const float* positions, int count,
-            int posCount, const SkPaint& paint) = 0;
+            int posCount, const Paint& paint) = 0;
     virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
-            float hOffset, float vOffset, const SkPaint& paint) = 0;
+            float hOffset, float vOffset, const Paint& paint) = 0;
 };
 
 }; // namespace android
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
index cfa9cd8..e63c5fa 100644
--- a/core/jni/android/graphics/CanvasProperty.cpp
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -16,6 +16,7 @@
 
 #include "jni.h"
 #include "GraphicsJNI.h"
+#include "Paint.h"
 #include <android_runtime/AndroidRuntime.h>
 
 #include <utils/RefBase.h>
@@ -32,7 +33,7 @@
 }
 
 static jlong createPaint(JNIEnv* env, jobject clazz, jlong paintPtr) {
-    const SkPaint* paint = reinterpret_cast<const SkPaint*>(paintPtr);
+    const Paint* paint = reinterpret_cast<const Paint*>(paintPtr);
     return reinterpret_cast<jlong>(new CanvasPropertyPaint(*paint));
 }
 
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 320c259..7c41c2e 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -370,12 +370,12 @@
     return c;
 }
 
-SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) {
+android::Paint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) {
     SkASSERT(env);
     SkASSERT(paint);
     SkASSERT(env->IsInstanceOf(paint, gPaint_class));
     jlong paintHandle = env->GetLongField(paint, gPaint_nativeInstanceID);
-    SkPaint* p = reinterpret_cast<SkPaint*>(paintHandle);
+    android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle);
     SkASSERT(p);
     return p;
 }
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 28a6edb..dcc97e5 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -12,9 +12,9 @@
 
 class SkBitmapRegionDecoder;
 class SkCanvas;
-class SkPaint;
 
 namespace android {
+class Paint;
 class TypefaceImpl;
 }
 
@@ -48,7 +48,7 @@
     static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
 
     static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
-    static SkPaint*  getNativePaint(JNIEnv*, jobject paint);
+    static android::Paint*  getNativePaint(JNIEnv*, jobject paint);
     static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
     static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index f02f118..c66437a 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -18,9 +18,9 @@
 #include <cutils/log.h>
 #include <string>
 
-#include "SkPaint.h"
 #include "SkPathMeasure.h"
 #include "minikin/Layout.h"
+#include "Paint.h"
 #include "TypefaceImpl.h"
 #include "MinikinSkia.h"
 
@@ -38,7 +38,7 @@
     return off + n;
 }
 
-std::string MinikinUtils::setLayoutProperties(Layout* layout, const SkPaint* paint, int bidiFlags,
+std::string MinikinUtils::setLayoutProperties(Layout* layout, const Paint* paint, int bidiFlags,
         TypefaceImpl* typeface) {
     TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
     layout->setFontCollection(resolvedFace->fFontCollection);
@@ -62,12 +62,12 @@
     return std::string(css);
 }
 
-float MinikinUtils::xOffsetForTextAlign(SkPaint* paint, const Layout& layout) {
+float MinikinUtils::xOffsetForTextAlign(Paint* paint, const Layout& layout) {
     switch (paint->getTextAlign()) {
-        case SkPaint::kCenter_Align:
+        case Paint::kCenter_Align:
             return layout.getAdvance() * -0.5f;
             break;
-        case SkPaint::kRight_Align:
+        case Paint::kRight_Align:
             return -layout.getAdvance();
             break;
         default:
@@ -76,13 +76,13 @@
     return 0;
 }
 
-float MinikinUtils::hOffsetForTextAlign(SkPaint* paint, const Layout& layout, const SkPath& path) {
+float MinikinUtils::hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path) {
     float align = 0;
     switch (paint->getTextAlign()) {
-        case SkPaint::kCenter_Align:
+        case Paint::kCenter_Align:
             align = -0.5f;
             break;
-        case SkPaint::kRight_Align:
+        case Paint::kRight_Align:
             align = -1;
             break;
         default:
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index 1663860..0562c3b1 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -16,7 +16,7 @@
 
 /**
  * Utilities for making Minikin work, especially from existing objects like
- * SkPaint and so on.
+ * Paint and so on.
  **/
 
  // TODO: does this really need to be separate from MinikinSkia?
@@ -24,6 +24,8 @@
 #ifndef ANDROID_MINIKIN_UTILS_H
 #define ANDROID_MINIKIN_UTILS_H
 
+#include "Paint.h"
+
 namespace android {
 
 // TODO: these should be defined in Minikin's Layout.h
@@ -43,15 +45,15 @@
 
 class MinikinUtils {
 public:
-    static std::string setLayoutProperties(Layout* layout, const SkPaint* paint, int bidiFlags,
+    static std::string setLayoutProperties(Layout* layout, const Paint* paint, int bidiFlags,
             TypefaceImpl* typeface);
 
-    static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);
+    static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
 
-    static float hOffsetForTextAlign(SkPaint* paint, const Layout& layout, const SkPath& path);
+    static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path);
     // f is a functor of type void f(size_t start, size_t end);
     template <typename F>
-    static void forFontRun(const Layout& layout, SkPaint* paint, F& f) {
+    static void forFontRun(const Layout& layout, Paint* paint, F& f) {
         float saveSkewX = paint->getTextSkewX();
         bool savefakeBold = paint->isFakeBoldText();
         MinikinFont* curFont = NULL;
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index 5f9a9b7..226f83e 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -7,6 +7,7 @@
 #include "SkUtils.h"
 #include "Utils.h"
 #include "CreateJavaOutputStreamAdaptor.h"
+#include "Paint.h"
 
 #include <androidfw/Asset.h>
 #include <androidfw/ResourceTypes.h>
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index e82e8a6..cf23771 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -23,6 +23,7 @@
 
 #include <Caches.h>
 
+#include "Paint.h"
 #include "Canvas.h"
 #include "SkCanvas.h"
 #include "SkRegion.h"
@@ -123,7 +124,7 @@
         SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
         const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         Res_png_9patch* chunk  = reinterpret_cast<Res_png_9patch*>(chunkHandle);
-        const SkPaint* paint   = reinterpret_cast<SkPaint*>(paintHandle);
+        const Paint* paint     = reinterpret_cast<Paint*>(paintHandle);
         SkASSERT(canvas);
         SkASSERT(boundsRectF);
         SkASSERT(bitmap);
@@ -142,7 +143,7 @@
         SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
         const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         Res_png_9patch* chunk  = reinterpret_cast<Res_png_9patch*>(chunkHandle);
-        const SkPaint* paint   = reinterpret_cast<SkPaint*>(paintHandle);
+        const Paint* paint     = reinterpret_cast<Paint*>(paintHandle);
         SkASSERT(canvas);
         SkASSERT(boundsRect);
         SkASSERT(bitmap);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 0ad390a..c06f0d2 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -39,6 +39,7 @@
 #include <minikin/Layout.h>
 #include "MinikinSkia.h"
 #include "MinikinUtils.h"
+#include "Paint.h"
 #include "TypefaceImpl.h"
 
 // temporary for debugging
@@ -61,47 +62,47 @@
 static jclass   gFontMetricsInt_class;
 static JMetricsID gFontMetricsInt_fieldID;
 
-static void defaultSettingsForAndroid(SkPaint* paint) {
+static void defaultSettingsForAndroid(Paint* paint) {
     // GlyphID encoding is required because we are using Harfbuzz shaping
-    paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+    paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
 
     SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
     paintOpts.setUseFontFallbacks(true);
     paint->setPaintOptionsAndroid(paintOpts);
 }
 
-class SkPaintGlue {
+class PaintGlue {
 public:
     enum MoveOpt {
         AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
     };
 
     static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         delete obj;
     }
 
     static jlong init(JNIEnv* env, jobject clazz) {
-        SkPaint* obj = new SkPaint();
+        Paint* obj = new Paint();
         defaultSettingsForAndroid(obj);
         return reinterpret_cast<jlong>(obj);
     }
 
     static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-        SkPaint* obj = new SkPaint(*paint);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        Paint* obj = new Paint(*paint);
         return reinterpret_cast<jlong>(obj);
     }
 
     static void reset(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         obj->reset();
         defaultSettingsForAndroid(obj);
     }
 
     static void assign(JNIEnv* env, jobject clazz, jlong dstPaintHandle, jlong srcPaintHandle) {
-        SkPaint* dst = reinterpret_cast<SkPaint*>(dstPaintHandle);
-        const SkPaint* src = reinterpret_cast<SkPaint*>(srcPaintHandle);
+        Paint* dst = reinterpret_cast<Paint*>(dstPaintHandle);
+        const Paint* src = reinterpret_cast<Paint*>(srcPaintHandle);
         *dst = *src;
     }
 
@@ -110,10 +111,10 @@
 
     static jint getFlags(JNIEnv* env, jobject paint) {
         NPE_CHECK_RETURN_ZERO(env, paint);
-        SkPaint* nativePaint = GraphicsJNI::getNativePaint(env, paint);
+        Paint* nativePaint = GraphicsJNI::getNativePaint(env, paint);
         uint32_t result = nativePaint->getFlags();
         result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away.
-        if (nativePaint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
+        if (nativePaint->getFilterLevel() != Paint::kNone_FilterLevel) {
             result |= sFilterBitmapFlag;
         }
         return static_cast<jint>(result);
@@ -121,11 +122,11 @@
 
     static void setFlags(JNIEnv* env, jobject paint, jint flags) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        SkPaint* nativePaint = GraphicsJNI::getNativePaint(env, paint);
+        Paint* nativePaint = GraphicsJNI::getNativePaint(env, paint);
         // Instead of modifying 0x02, change the filter level.
         nativePaint->setFilterLevel(flags & sFilterBitmapFlag
-                ? SkPaint::kLow_FilterLevel
-                : SkPaint::kNone_FilterLevel);
+                ? Paint::kLow_FilterLevel
+                : Paint::kNone_FilterLevel);
         // Don't pass through filter flag, which is no longer stored in paint's flags.
         flags &= ~sFilterBitmapFlag;
         // Use the existing value for 0x02.
@@ -137,13 +138,13 @@
     static jint getHinting(JNIEnv* env, jobject paint) {
         NPE_CHECK_RETURN_ZERO(env, paint);
         return GraphicsJNI::getNativePaint(env, paint)->getHinting()
-                == SkPaint::kNo_Hinting ? 0 : 1;
+                == Paint::kNo_Hinting ? 0 : 1;
     }
 
     static void setHinting(JNIEnv* env, jobject paint, jint mode) {
         NPE_CHECK_RETURN_VOID(env, paint);
         GraphicsJNI::getNativePaint(env, paint)->setHinting(
-                mode == 0 ? SkPaint::kNo_Hinting : SkPaint::kNormal_Hinting);
+                mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting);
     }
 
     static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) {
@@ -179,7 +180,7 @@
     static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
         NPE_CHECK_RETURN_VOID(env, paint);
         GraphicsJNI::getNativePaint(env, paint)->setFilterLevel(
-                filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
+                filterBitmap ? Paint::kLow_FilterLevel : Paint::kNone_FilterLevel);
     }
 
     static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
@@ -188,13 +189,13 @@
     }
 
     static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         return static_cast<jint>(obj->getStyle());
     }
 
     static void setStyle(JNIEnv* env, jobject clazz, jlong objHandle, jint styleHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
-        SkPaint::Style style = static_cast<SkPaint::Style>(styleHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
+        Paint::Style style = static_cast<Paint::Style>(styleHandle);
         obj->setStyle(style);
     }
 
@@ -243,83 +244,83 @@
     }
 
     static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         return static_cast<jint>(obj->getStrokeCap());
     }
 
     static void setStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle, jint capHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
-        SkPaint::Cap cap = static_cast<SkPaint::Cap>(capHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
+        Paint::Cap cap = static_cast<Paint::Cap>(capHandle);
         obj->setStrokeCap(cap);
     }
 
     static jint getStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         return static_cast<jint>(obj->getStrokeJoin());
     }
 
     static void setStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle, jint joinHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
-        SkPaint::Join join = (SkPaint::Join) joinHandle;
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
+        Paint::Join join = (Paint::Join) joinHandle;
         obj->setStrokeJoin(join);
     }
 
     static jboolean getFillPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong dstHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
         SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
         return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE;
     }
 
     static jlong setShader(JNIEnv* env, jobject clazz, jlong objHandle, jlong shaderHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
         return reinterpret_cast<jlong>(obj->setShader(shader));
     }
 
     static jlong setColorFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong filterHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint *>(objHandle);
+        Paint* obj = reinterpret_cast<Paint *>(objHandle);
         SkColorFilter* filter  = reinterpret_cast<SkColorFilter *>(filterHandle);
         return reinterpret_cast<jlong>(obj->setColorFilter(filter));
     }
 
     static jlong setXfermode(JNIEnv* env, jobject clazz, jlong objHandle, jlong xfermodeHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkXfermode* xfermode = reinterpret_cast<SkXfermode*>(xfermodeHandle);
         return reinterpret_cast<jlong>(obj->setXfermode(xfermode));
     }
 
     static jlong setPathEffect(JNIEnv* env, jobject clazz, jlong objHandle, jlong effectHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkPathEffect* effect  = reinterpret_cast<SkPathEffect*>(effectHandle);
         return reinterpret_cast<jlong>(obj->setPathEffect(effect));
     }
 
     static jlong setMaskFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong maskfilterHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkMaskFilter* maskfilter  = reinterpret_cast<SkMaskFilter*>(maskfilterHandle);
         return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter));
     }
 
     static jlong setTypeface(JNIEnv* env, jobject clazz, jlong objHandle, jlong typefaceHandle) {
-        // TODO: in Paint refactoring, set typeface on android Paint, not SkPaint
+        // TODO: in Paint refactoring, set typeface on android Paint, not Paint
         return NULL;
     }
 
     static jlong setRasterizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong rasterizerHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkAutoTUnref<SkRasterizer> rasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle));
         return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer));
     }
 
     static jint getTextAlign(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         return static_cast<jint>(obj->getTextAlign());
     }
 
     static void setTextAlign(JNIEnv* env, jobject clazz, jlong objHandle, jint alignHandle) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
-        SkPaint::Align align = static_cast<SkPaint::Align>(alignHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
+        Paint::Align align = static_cast<Paint::Align>(alignHandle);
         obj->setTextAlign(align);
     }
 
@@ -364,7 +365,7 @@
     }
 
     static void setTextLocale(JNIEnv* env, jobject clazz, jlong objHandle, jstring locale) {
-        SkPaint* obj = reinterpret_cast<SkPaint*>(objHandle);
+        Paint* obj = reinterpret_cast<Paint*>(objHandle);
         ScopedUtfChars localeChars(env, locale);
         char langTag[ULOC_FULLNAME_CAPACITY];
         toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
@@ -376,14 +377,14 @@
 
     static jboolean isElegantTextHeight(JNIEnv* env, jobject paint) {
         NPE_CHECK_RETURN_ZERO(env, paint);
-        SkPaint* obj = GraphicsJNI::getNativePaint(env, paint);
+        Paint* obj = GraphicsJNI::getNativePaint(env, paint);
         SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
         return paintOpts.getFontVariant() == SkPaintOptionsAndroid::kElegant_Variant;
     }
 
     static void setElegantTextHeight(JNIEnv* env, jobject paint, jboolean aa) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        SkPaint* obj = GraphicsJNI::getNativePaint(env, paint);
+        Paint* obj = GraphicsJNI::getNativePaint(env, paint);
         SkPaintOptionsAndroid::FontVariant variant =
             aa ? SkPaintOptionsAndroid::kElegant_Variant :
             SkPaintOptionsAndroid::kDefault_Variant;
@@ -422,13 +423,13 @@
         GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(skewX);
     }
 
-    static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, SkPaint::FontMetrics *metrics) {
+    static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, Paint::FontMetrics *metrics) {
         const int kElegantTop = 2500;
         const int kElegantBottom = -1000;
         const int kElegantAscent = 1900;
         const int kElegantDescent = -500;
         const int kElegantLeading = 0;
-        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+        Paint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         TypefaceImpl* typeface = GraphicsJNI::getNativeTypeface(env, jpaint);
         typeface = TypefaceImpl_resolveDefault(typeface);
         FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
@@ -456,21 +457,21 @@
 
     static jfloat ascent(JNIEnv* env, jobject paint) {
         NPE_CHECK_RETURN_ZERO(env, paint);
-        SkPaint::FontMetrics metrics;
+        Paint::FontMetrics metrics;
         getMetricsInternal(env, paint, &metrics);
         return SkScalarToFloat(metrics.fAscent);
     }
 
     static jfloat descent(JNIEnv* env, jobject paint) {
         NPE_CHECK_RETURN_ZERO(env, paint);
-        SkPaint::FontMetrics metrics;
+        Paint::FontMetrics metrics;
         getMetricsInternal(env, paint, &metrics);
         return SkScalarToFloat(metrics.fDescent);
     }
 
     static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
         NPE_CHECK_RETURN_ZERO(env, paint);
-        SkPaint::FontMetrics metrics;
+        Paint::FontMetrics metrics;
         SkScalar spacing = getMetricsInternal(env, paint, &metrics);
 
         if (metricsObj) {
@@ -486,7 +487,7 @@
 
     static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
         NPE_CHECK_RETURN_ZERO(env, paint);
-        SkPaint::FontMetrics metrics;
+        Paint::FontMetrics metrics;
 
         getMetricsInternal(env, paint, &metrics);
         int ascent = SkScalarRoundToInt(metrics.fAscent);
@@ -518,7 +519,7 @@
             return 0;
         }
 
-        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+        Paint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         const jchar* textArray = env->GetCharArrayElements(text, NULL);
         jfloat result = 0;
 
@@ -547,7 +548,7 @@
         }
 
         const jchar* textArray = env->GetStringChars(text, NULL);
-        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+        Paint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         jfloat width = 0;
 
         Layout layout;
@@ -570,7 +571,7 @@
         }
 
         const jchar* textArray = env->GetStringChars(text, NULL);
-        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+        Paint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         jfloat width = 0;
 
         Layout layout;
@@ -583,7 +584,7 @@
         return width;
     }
 
-    static int dotextwidths(JNIEnv* env, SkPaint* paint, TypefaceImpl* typeface, const jchar text[], int count,
+    static int dotextwidths(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar text[], int count,
             jfloatArray widths, jint bidiFlags) {
         NPE_CHECK_RETURN_ZERO(env, paint);
         NPE_CHECK_RETURN_ZERO(env, text);
@@ -614,7 +615,7 @@
 
     static jint getTextWidths___CIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray text,
             jint index, jint count, jint bidiFlags, jfloatArray widths) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetCharArrayElements(text, NULL);
         count = dotextwidths(env, paint, typeface, textArray + index, count, widths, bidiFlags);
@@ -625,7 +626,7 @@
 
     static jint getTextWidths__StringIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring text,
             jint start, jint end, jint bidiFlags, jfloatArray widths) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
         int count = dotextwidths(env, paint, typeface, textArray + start, end - start, widths, bidiFlags);
@@ -633,7 +634,7 @@
         return count;
     }
 
-    static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, TypefaceImpl* typeface, const jchar *text,
+    static jfloat doTextRunAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface, const jchar *text,
                                     jint start, jint count, jint contextCount, jboolean isRtl,
                                     jfloatArray advances, jint advancesIndex) {
         NPE_CHECK_RETURN_ZERO(env, paint);
@@ -675,7 +676,7 @@
             jlong typefaceHandle,
             jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
             jboolean isRtl, jfloatArray advances, jint advancesIndex) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         jchar* textArray = env->GetCharArrayElements(text, NULL);
         jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextIndex,
@@ -688,7 +689,7 @@
             jlong typefaceHandle,
             jstring text, jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl,
             jfloatArray advances, jint advancesIndex) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
         jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextStart,
@@ -698,7 +699,7 @@
         return result;
     }
 
-    static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
+    static jint doTextRunCursor(JNIEnv *env, Paint* paint, const jchar *text, jint start,
             jint count, jint flags, jint offset, jint opt) {
         GraphemeBreak::MoveOpt moveOpt = GraphemeBreak::MoveOpt(opt);
         size_t result = GraphemeBreak::getTextRunCursor(text, start, count, offset, moveOpt);
@@ -707,7 +708,7 @@
 
     static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
             jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         jchar* textArray = env->GetCharArrayElements(text, NULL);
         jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, dir,
                 offset, cursorOpt);
@@ -717,7 +718,7 @@
 
     static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
             jint contextStart, jint contextEnd, jint dir, jint offset, jint cursorOpt) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
         jint result = doTextRunCursor(env, paint, textArray, contextStart,
                 contextEnd - contextStart, dir, offset, cursorOpt);
@@ -727,7 +728,7 @@
 
     class GetTextFunctor {
     public:
-        GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, SkPaint* paint,
+        GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, Paint* paint,
                     uint16_t* glyphs, SkPoint* pos)
                 : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
         }
@@ -750,13 +751,13 @@
         SkPath* path;
         jfloat x;
         jfloat y;
-        SkPaint* paint;
+        Paint* paint;
         uint16_t* glyphs;
         SkPoint* pos;
         SkPath tmpPath;
     };
 
-    static void getTextPath(JNIEnv* env, SkPaint* paint, TypefaceImpl* typeface, const jchar* text,
+    static void getTextPath(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar* text,
             jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
         Layout layout;
         std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
@@ -766,9 +767,9 @@
         SkPoint* pos = new SkPoint[nGlyphs];
 
         x += MinikinUtils::xOffsetForTextAlign(paint, layout);
-        SkPaint::Align align = paint->getTextAlign();
-        paint->setTextAlign(SkPaint::kLeft_Align);
-        paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        Paint::Align align = paint->getTextAlign();
+        paint->setTextAlign(Paint::kLeft_Align);
+        paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
         GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
         MinikinUtils::forFontRun(layout, paint, f);
         paint->setTextAlign(align);
@@ -779,7 +780,7 @@
     static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle,
             jlong typefaceHandle, jint bidiFlags,
             jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
         const jchar* textArray = env->GetCharArrayElements(text, NULL);
@@ -790,7 +791,7 @@
     static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle,
             jlong typefaceHandle, jint bidiFlags,
             jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
@@ -800,7 +801,7 @@
 
     static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius,
                                jfloat dx, jfloat dy, jint color) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         if (radius <= 0) {
             paint->setLooper(NULL);
         }
@@ -811,13 +812,13 @@
     }
 
     static jboolean hasShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
     }
 
-    static int breakText(JNIEnv* env, const SkPaint& paint, TypefaceImpl* typeface, const jchar text[],
+    static int breakText(JNIEnv* env, const Paint& paint, TypefaceImpl* typeface, const jchar text[],
                          int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
-                         SkPaint::TextBufferDirection textBufferDirection) {
+                         Paint::TextBufferDirection textBufferDirection) {
         size_t measuredCount = 0;
         float measured = 0;
 
@@ -826,7 +827,7 @@
         layout.doLayout(text, 0, count, count, css);
         float* advances = new float[count];
         layout.getAdvances(advances);
-        const bool forwardScan = (textBufferDirection == SkPaint::kForward_TextBufferDirection);
+        const bool forwardScan = (textBufferDirection == Paint::kForward_TextBufferDirection);
         for (int i = 0; i < count; i++) {
             // traverse in the given direction
             int index = forwardScan ? i : (count - i - 1);
@@ -854,16 +855,16 @@
             jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
         NPE_CHECK_RETURN_ZERO(env, jtext);
 
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
-        SkPaint::TextBufferDirection tbd;
+        Paint::TextBufferDirection tbd;
         if (count < 0) {
-            tbd = SkPaint::kBackward_TextBufferDirection;
+            tbd = Paint::kBackward_TextBufferDirection;
             count = -count;
         }
         else {
-            tbd = SkPaint::kForward_TextBufferDirection;
+            tbd = Paint::kForward_TextBufferDirection;
         }
 
         if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
@@ -883,12 +884,12 @@
                 jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) {
         NPE_CHECK_RETURN_ZERO(env, jtext);
 
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
-        SkPaint::TextBufferDirection tbd = forwards ?
-                                        SkPaint::kForward_TextBufferDirection :
-                                        SkPaint::kBackward_TextBufferDirection;
+        Paint::TextBufferDirection tbd = forwards ?
+                                        Paint::kForward_TextBufferDirection :
+                                        Paint::kBackward_TextBufferDirection;
 
         int count = env->GetStringLength(jtext);
         const jchar* text = env->GetStringChars(jtext, NULL);
@@ -898,7 +899,7 @@
     }
 
     static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds,
-            const SkPaint& paint, TypefaceImpl* typeface, jint bidiFlags) {
+            const Paint& paint, TypefaceImpl* typeface, jint bidiFlags) {
         SkRect  r;
         SkIRect ir;
 
@@ -917,7 +918,7 @@
 
     static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
                                 jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
-        const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);;
+        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);;
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
         doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags);
@@ -926,7 +927,7 @@
 
     static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
                         jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
-        const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetCharArrayElements(text, NULL);
         doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags);
@@ -937,83 +938,83 @@
 };
 
 static JNINativeMethod methods[] = {
-    {"finalizer", "(J)V", (void*) SkPaintGlue::finalizer},
-    {"native_init","()J", (void*) SkPaintGlue::init},
-    {"native_initWithPaint","(J)J", (void*) SkPaintGlue::initWithPaint},
-    {"native_reset","(J)V", (void*) SkPaintGlue::reset},
-    {"native_set","(JJ)V", (void*) SkPaintGlue::assign},
-    {"getFlags","()I", (void*) SkPaintGlue::getFlags},
-    {"setFlags","(I)V", (void*) SkPaintGlue::setFlags},
-    {"getHinting","()I", (void*) SkPaintGlue::getHinting},
-    {"setHinting","(I)V", (void*) SkPaintGlue::setHinting},
-    {"setAntiAlias","(Z)V", (void*) SkPaintGlue::setAntiAlias},
-    {"setSubpixelText","(Z)V", (void*) SkPaintGlue::setSubpixelText},
-    {"setLinearText","(Z)V", (void*) SkPaintGlue::setLinearText},
-    {"setUnderlineText","(Z)V", (void*) SkPaintGlue::setUnderlineText},
-    {"setStrikeThruText","(Z)V", (void*) SkPaintGlue::setStrikeThruText},
-    {"setFakeBoldText","(Z)V", (void*) SkPaintGlue::setFakeBoldText},
-    {"setFilterBitmap","(Z)V", (void*) SkPaintGlue::setFilterBitmap},
-    {"setDither","(Z)V", (void*) SkPaintGlue::setDither},
-    {"native_getStyle","(J)I", (void*) SkPaintGlue::getStyle},
-    {"native_setStyle","(JI)V", (void*) SkPaintGlue::setStyle},
-    {"getColor","()I", (void*) SkPaintGlue::getColor},
-    {"setColor","(I)V", (void*) SkPaintGlue::setColor},
-    {"getAlpha","()I", (void*) SkPaintGlue::getAlpha},
-    {"setAlpha","(I)V", (void*) SkPaintGlue::setAlpha},
-    {"getStrokeWidth","()F", (void*) SkPaintGlue::getStrokeWidth},
-    {"setStrokeWidth","(F)V", (void*) SkPaintGlue::setStrokeWidth},
-    {"getStrokeMiter","()F", (void*) SkPaintGlue::getStrokeMiter},
-    {"setStrokeMiter","(F)V", (void*) SkPaintGlue::setStrokeMiter},
-    {"native_getStrokeCap","(J)I", (void*) SkPaintGlue::getStrokeCap},
-    {"native_setStrokeCap","(JI)V", (void*) SkPaintGlue::setStrokeCap},
-    {"native_getStrokeJoin","(J)I", (void*) SkPaintGlue::getStrokeJoin},
-    {"native_setStrokeJoin","(JI)V", (void*) SkPaintGlue::setStrokeJoin},
-    {"native_getFillPath","(JJJ)Z", (void*) SkPaintGlue::getFillPath},
-    {"native_setShader","(JJ)J", (void*) SkPaintGlue::setShader},
-    {"native_setColorFilter","(JJ)J", (void*) SkPaintGlue::setColorFilter},
-    {"native_setXfermode","(JJ)J", (void*) SkPaintGlue::setXfermode},
-    {"native_setPathEffect","(JJ)J", (void*) SkPaintGlue::setPathEffect},
-    {"native_setMaskFilter","(JJ)J", (void*) SkPaintGlue::setMaskFilter},
-    {"native_setTypeface","(JJ)J", (void*) SkPaintGlue::setTypeface},
-    {"native_setRasterizer","(JJ)J", (void*) SkPaintGlue::setRasterizer},
-    {"native_getTextAlign","(J)I", (void*) SkPaintGlue::getTextAlign},
-    {"native_setTextAlign","(JI)V", (void*) SkPaintGlue::setTextAlign},
-    {"native_setTextLocale","(JLjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale},
-    {"isElegantTextHeight","()Z", (void*) SkPaintGlue::isElegantTextHeight},
-    {"setElegantTextHeight","(Z)V", (void*) SkPaintGlue::setElegantTextHeight},
-    {"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
-    {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
-    {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
-    {"setTextScaleX","(F)V", (void*) SkPaintGlue::setTextScaleX},
-    {"getTextSkewX","()F", (void*) SkPaintGlue::getTextSkewX},
-    {"setTextSkewX","(F)V", (void*) SkPaintGlue::setTextSkewX},
-    {"ascent","()F", (void*) SkPaintGlue::ascent},
-    {"descent","()F", (void*) SkPaintGlue::descent},
-    {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)SkPaintGlue::getFontMetrics},
-    {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)SkPaintGlue::getFontMetricsInt},
-    {"native_measureText","([CIII)F", (void*) SkPaintGlue::measureText_CIII},
-    {"native_measureText","(Ljava/lang/String;I)F", (void*) SkPaintGlue::measureText_StringI},
-    {"native_measureText","(Ljava/lang/String;III)F", (void*) SkPaintGlue::measureText_StringIII},
-    {"native_breakText","(JJ[CIIFI[F)I", (void*) SkPaintGlue::breakTextC},
-    {"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
-    {"native_getTextWidths","(JJ[CIII[F)I", (void*) SkPaintGlue::getTextWidths___CIII_F},
-    {"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) SkPaintGlue::getTextWidths__StringIII_F},
+    {"finalizer", "(J)V", (void*) PaintGlue::finalizer},
+    {"native_init","()J", (void*) PaintGlue::init},
+    {"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
+    {"native_reset","(J)V", (void*) PaintGlue::reset},
+    {"native_set","(JJ)V", (void*) PaintGlue::assign},
+    {"getFlags","()I", (void*) PaintGlue::getFlags},
+    {"setFlags","(I)V", (void*) PaintGlue::setFlags},
+    {"getHinting","()I", (void*) PaintGlue::getHinting},
+    {"setHinting","(I)V", (void*) PaintGlue::setHinting},
+    {"setAntiAlias","(Z)V", (void*) PaintGlue::setAntiAlias},
+    {"setSubpixelText","(Z)V", (void*) PaintGlue::setSubpixelText},
+    {"setLinearText","(Z)V", (void*) PaintGlue::setLinearText},
+    {"setUnderlineText","(Z)V", (void*) PaintGlue::setUnderlineText},
+    {"setStrikeThruText","(Z)V", (void*) PaintGlue::setStrikeThruText},
+    {"setFakeBoldText","(Z)V", (void*) PaintGlue::setFakeBoldText},
+    {"setFilterBitmap","(Z)V", (void*) PaintGlue::setFilterBitmap},
+    {"setDither","(Z)V", (void*) PaintGlue::setDither},
+    {"native_getStyle","(J)I", (void*) PaintGlue::getStyle},
+    {"native_setStyle","(JI)V", (void*) PaintGlue::setStyle},
+    {"getColor","()I", (void*) PaintGlue::getColor},
+    {"setColor","(I)V", (void*) PaintGlue::setColor},
+    {"getAlpha","()I", (void*) PaintGlue::getAlpha},
+    {"setAlpha","(I)V", (void*) PaintGlue::setAlpha},
+    {"getStrokeWidth","()F", (void*) PaintGlue::getStrokeWidth},
+    {"setStrokeWidth","(F)V", (void*) PaintGlue::setStrokeWidth},
+    {"getStrokeMiter","()F", (void*) PaintGlue::getStrokeMiter},
+    {"setStrokeMiter","(F)V", (void*) PaintGlue::setStrokeMiter},
+    {"native_getStrokeCap","(J)I", (void*) PaintGlue::getStrokeCap},
+    {"native_setStrokeCap","(JI)V", (void*) PaintGlue::setStrokeCap},
+    {"native_getStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin},
+    {"native_setStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin},
+    {"native_getFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath},
+    {"native_setShader","(JJ)J", (void*) PaintGlue::setShader},
+    {"native_setColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter},
+    {"native_setXfermode","(JJ)J", (void*) PaintGlue::setXfermode},
+    {"native_setPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect},
+    {"native_setMaskFilter","(JJ)J", (void*) PaintGlue::setMaskFilter},
+    {"native_setTypeface","(JJ)J", (void*) PaintGlue::setTypeface},
+    {"native_setRasterizer","(JJ)J", (void*) PaintGlue::setRasterizer},
+    {"native_getTextAlign","(J)I", (void*) PaintGlue::getTextAlign},
+    {"native_setTextAlign","(JI)V", (void*) PaintGlue::setTextAlign},
+    {"native_setTextLocale","(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale},
+    {"isElegantTextHeight","()Z", (void*) PaintGlue::isElegantTextHeight},
+    {"setElegantTextHeight","(Z)V", (void*) PaintGlue::setElegantTextHeight},
+    {"getTextSize","()F", (void*) PaintGlue::getTextSize},
+    {"setTextSize","(F)V", (void*) PaintGlue::setTextSize},
+    {"getTextScaleX","()F", (void*) PaintGlue::getTextScaleX},
+    {"setTextScaleX","(F)V", (void*) PaintGlue::setTextScaleX},
+    {"getTextSkewX","()F", (void*) PaintGlue::getTextSkewX},
+    {"setTextSkewX","(F)V", (void*) PaintGlue::setTextSkewX},
+    {"ascent","()F", (void*) PaintGlue::ascent},
+    {"descent","()F", (void*) PaintGlue::descent},
+    {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)PaintGlue::getFontMetrics},
+    {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)PaintGlue::getFontMetricsInt},
+    {"native_measureText","([CIII)F", (void*) PaintGlue::measureText_CIII},
+    {"native_measureText","(Ljava/lang/String;I)F", (void*) PaintGlue::measureText_StringI},
+    {"native_measureText","(Ljava/lang/String;III)F", (void*) PaintGlue::measureText_StringIII},
+    {"native_breakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC},
+    {"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
+    {"native_getTextWidths","(JJ[CIII[F)I", (void*) PaintGlue::getTextWidths___CIII_F},
+    {"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) PaintGlue::getTextWidths__StringIII_F},
     {"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",
-        (void*) SkPaintGlue::getTextRunAdvances___CIIIIZ_FI},
+        (void*) PaintGlue::getTextRunAdvances___CIIIIZ_FI},
     {"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F",
-        (void*) SkPaintGlue::getTextRunAdvances__StringIIIIZ_FI},
+        (void*) PaintGlue::getTextRunAdvances__StringIIIIZ_FI},
 
-    {"native_getTextRunCursor", "(J[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C},
+    {"native_getTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
     {"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
-        (void*) SkPaintGlue::getTextRunCursor__String},
-    {"native_getTextPath","(JJI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
-    {"native_getTextPath","(JJILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
+        (void*) PaintGlue::getTextRunCursor__String},
+    {"native_getTextPath","(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
+    {"native_getTextPath","(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
     {"nativeGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V",
-                                        (void*) SkPaintGlue::getStringBounds },
+                                        (void*) PaintGlue::getStringBounds },
     {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
-                                    (void*) SkPaintGlue::getCharArrayBounds },
-    {"native_setShadowLayer", "(JFFFI)V", (void*)SkPaintGlue::setShadowLayer},
-    {"native_hasShadowLayer", "(J)Z", (void*)SkPaintGlue::hasShadowLayer}
+                                    (void*) PaintGlue::getCharArrayBounds },
+    {"native_setShadowLayer", "(JFFFI)V", (void*)PaintGlue::setShadowLayer},
+    {"native_hasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer}
 };
 
 static jfieldID req_fieldID(jfieldID id) {
diff --git a/core/jni/android/graphics/Paint.h b/core/jni/android/graphics/Paint.h
new file mode 100644
index 0000000..239b217
--- /dev/null
+++ b/core/jni/android/graphics/Paint.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GRAPHICS_PAINT_H
+#define ANDROID_GRAPHICS_PAINT_H
+
+#include <SkPaint.h>
+
+namespace android {
+
+class Paint : public SkPaint {
+public:
+    Paint();
+    Paint(const Paint& paint);
+    ~Paint();
+
+    Paint& operator=(const Paint& other);
+
+    friend bool operator==(const Paint& a, const Paint& b);
+    friend bool operator!=(const Paint& a, const Paint& b) {
+        return !(a == b);
+    }
+
+private:
+};
+
+}  // namespace android
+
+#endif // ANDROID_GRAPHICS_PAINT_H
diff --git a/core/jni/android/graphics/PaintImpl.cpp b/core/jni/android/graphics/PaintImpl.cpp
new file mode 100644
index 0000000..6baae76
--- /dev/null
+++ b/core/jni/android/graphics/PaintImpl.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include "Paint.h"
+#include <SkPaint.h>
+
+#define LOG_TAG "Paint"
+#include <cutils/log.h>
+
+namespace android {
+
+Paint::Paint() : SkPaint() {
+}
+
+Paint::Paint(const Paint& paint) : SkPaint(paint) {
+}
+
+Paint::~Paint() {
+}
+
+Paint& Paint::operator=(const Paint& other) {
+    SkPaint::operator=(other);
+    return *this;
+}
+
+bool operator==(const Paint& a, const Paint& b) {
+    return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b);
+}
+
+}
diff --git a/core/jni/android/graphics/Rasterizer.cpp b/core/jni/android/graphics/Rasterizer.cpp
index a05d19b..2b1aca1 100644
--- a/core/jni/android/graphics/Rasterizer.cpp
+++ b/core/jni/android/graphics/Rasterizer.cpp
@@ -22,6 +22,7 @@
 
 #include "jni.h"
 #include "GraphicsJNI.h"
+#include "Paint.h"
 #include "SkLayerRasterizer.h"
 #include <android_runtime/AndroidRuntime.h>
 
@@ -79,7 +80,7 @@
 
     static void addLayer(JNIEnv* env, jobject, jlong layerHandle, jlong paintHandle, jfloat dx, jfloat dy) {
         NativeLayerRasterizer* nr = reinterpret_cast<NativeLayerRasterizer *>(layerHandle);
-        const SkPaint* paint = reinterpret_cast<SkPaint *>(paintHandle);
+        const Paint* paint = reinterpret_cast<Paint *>(paintHandle);
         SkASSERT(nr);
         SkASSERT(paint);
         nr->fBuilder.addLayer(*paint, dx, dy);
diff --git a/core/jni/android/graphics/SkiaCanvas.cpp b/core/jni/android/graphics/SkiaCanvas.cpp
index a4e0d28..f87033b 100644
--- a/core/jni/android/graphics/SkiaCanvas.cpp
+++ b/core/jni/android/graphics/SkiaCanvas.cpp
@@ -34,6 +34,7 @@
 #include "MinikinSkia.h"
 #include "MinikinUtils.h"
 
+#include "Paint.h"
 #include "TypefaceImpl.h"
 
 #include "unicode/ubidi.h"
@@ -68,7 +69,7 @@
     virtual void restoreToCount(int saveCount);
 
     virtual int saveLayer(float left, float top, float right, float bottom,
-                const SkPaint* paint, SkCanvas::SaveFlags flags);
+                const Paint* paint, SkCanvas::SaveFlags flags);
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
             int alpha, SkCanvas::SaveFlags flags);
 
@@ -90,39 +91,39 @@
     virtual void setDrawFilter(SkDrawFilter* drawFilter);
 
     virtual void drawColor(int color, SkXfermode::Mode mode);
-    virtual void drawPaint(const SkPaint& paint);
+    virtual void drawPaint(const Paint& paint);
 
-    virtual void drawPoint(float x, float y, const SkPaint& paint);
-    virtual void drawPoints(const float* points, int count, const SkPaint& paint);
+    virtual void drawPoint(float x, float y, const Paint& paint);
+    virtual void drawPoints(const float* points, int count, const Paint& paint);
     virtual void drawLine(float startX, float startY, float stopX, float stopY,
-            const SkPaint& paint);
-    virtual void drawLines(const float* points, int count, const SkPaint& paint);
-    virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
+            const Paint& paint);
+    virtual void drawLines(const float* points, int count, const Paint& paint);
+    virtual void drawRect(float left, float top, float right, float bottom, const Paint& paint);
     virtual void drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, const SkPaint& paint);
-    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
-    virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
+            float rx, float ry, const Paint& paint);
+    virtual void drawCircle(float x, float y, float radius, const Paint& paint);
+    virtual void drawOval(float left, float top, float right, float bottom, const Paint& paint);
     virtual void drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint);
-    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+            float startAngle, float sweepAngle, bool useCenter, const Paint& paint);
+    virtual void drawPath(const SkPath& path, const Paint& paint);
     virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
             const float* verts, const float* tex, const int* colors,
-            const uint16_t* indices, int indexCount, const SkPaint& paint);
+            const uint16_t* indices, int indexCount, const Paint& paint);
 
-    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
-    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const Paint* paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const Paint* paint);
     virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, const SkPaint* paint);
+            float dstRight, float dstBottom, const Paint* paint);
     virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
-            const float* vertices, const int* colors, const SkPaint* paint);
+            const float* vertices, const int* colors, const Paint* paint);
 
     virtual void drawText(const uint16_t* text, int start, int count, int contextCount,
-            float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface);
+            float x, float y, int bidiFlags, const Paint& paint, TypefaceImpl* typeface);
     virtual void drawPosText(const uint16_t* text, const float* positions, int count,
-            int posCount, const SkPaint& paint);
+            int posCount, const Paint& paint);
     virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
-            float hOffset, float vOffset, const SkPaint& paint);
+            float hOffset, float vOffset, const Paint& paint);
 
 private:
     struct SaveRec {
@@ -134,9 +135,9 @@
     void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount);
     void applyClips(const SkTArray<SkClipStack::Element>& clips);
 
-    void drawPoints(const float* points, int count, const SkPaint& paint,
+    void drawPoints(const float* points, int count, const Paint& paint,
                     SkCanvas::PointMode mode);
-    void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
+    void drawTextDecorations(float x, float y, float length, const Paint& paint);
 
     SkAutoTUnref<SkCanvas> mCanvas;
     SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
@@ -284,7 +285,7 @@
 }
 
 int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
-            const SkPaint* paint, SkCanvas::SaveFlags flags) {
+            const Paint* paint, SkCanvas::SaveFlags flags) {
     SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
     int count = mCanvas->saveLayer(&bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
     recordPartialSave(flags);
@@ -466,7 +467,7 @@
     mCanvas->drawColor(color, mode);
 }
 
-void SkiaCanvas::drawPaint(const SkPaint& paint) {
+void SkiaCanvas::drawPaint(const Paint& paint) {
     mCanvas->drawPaint(paint);
 }
 
@@ -474,7 +475,7 @@
 // Canvas draw operations: Geometry
 // ----------------------------------------------------------------------------
 
-void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint,
+void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint,
                             SkCanvas::PointMode mode) {
     // convert the floats into SkPoints
     count >>= 1;    // now it is the number of points
@@ -488,57 +489,57 @@
 }
 
 
-void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
+void SkiaCanvas::drawPoint(float x, float y, const Paint& paint) {
     mCanvas->drawPoint(x, y, paint);
 }
 
-void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
+void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint) {
     this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
 }
 
 void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
-                          const SkPaint& paint) {
+                          const Paint& paint) {
     mCanvas->drawLine(startX, startY, stopX, stopY, paint);
 }
 
-void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
+void SkiaCanvas::drawLines(const float* points, int count, const Paint& paint) {
     this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
 }
 
 void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
-        const SkPaint& paint) {
+        const Paint& paint) {
     mCanvas->drawRectCoords(left, top, right, bottom, paint);
 
 }
 
 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
-        float rx, float ry, const SkPaint& paint) {
+        float rx, float ry, const Paint& paint) {
     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->drawRoundRect(rect, rx, ry, paint);
 }
 
-void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
+void SkiaCanvas::drawCircle(float x, float y, float radius, const Paint& paint) {
     mCanvas->drawCircle(x, y, radius, paint);
 }
 
-void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
+void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const Paint& paint) {
     SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->drawOval(oval, paint);
 }
 
 void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+        float startAngle, float sweepAngle, bool useCenter, const Paint& paint) {
     SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
 }
 
-void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+void SkiaCanvas::drawPath(const SkPath& path, const Paint& paint) {
     mCanvas->drawPath(path, paint);
 }
 
 void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
                               const float* verts, const float* texs, const int* colors,
-                              const uint16_t* indices, int indexCount, const SkPaint& paint) {
+                              const uint16_t* indices, int indexCount, const Paint& paint) {
 #ifndef SK_SCALAR_IS_FLOAT
     SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
 #endif
@@ -551,24 +552,24 @@
 // Canvas draw operations: Bitmaps
 // ----------------------------------------------------------------------------
 
-void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
+void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const Paint* paint) {
     mCanvas->drawBitmap(bitmap, left, top, paint);
 }
 
-void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
+void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const Paint* paint) {
     mCanvas->drawBitmapMatrix(bitmap, matrix, paint);
 }
 
 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
                             float srcRight, float srcBottom, float dstLeft, float dstTop,
-                            float dstRight, float dstBottom, const SkPaint* paint) {
+                            float dstRight, float dstBottom, const Paint* paint) {
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
     mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint);
 }
 
 void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
-        const float* vertices, const int* colors, const SkPaint* paint) {
+        const float* vertices, const int* colors, const Paint* paint) {
 
     const int ptCount = (meshWidth + 1) * (meshHeight + 1);
     const int indexCount = meshWidth * meshHeight * 6;
@@ -650,7 +651,7 @@
 #endif
 
     // cons-up a shader for the bitmap
-    SkPaint tmpPaint;
+    Paint tmpPaint;
     if (paint) {
         tmpPaint = *paint;
     }
@@ -670,7 +671,7 @@
 
 class DrawTextFunctor {
 public:
-    DrawTextFunctor(const Layout& layout, SkCanvas* canvas, float x, float y, SkPaint* paint,
+    DrawTextFunctor(const Layout& layout, SkCanvas* canvas, float x, float y, Paint* paint,
                 uint16_t* glyphs, SkPoint* pos)
             : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
                 pos(pos) { }
@@ -688,13 +689,13 @@
     SkCanvas* canvas;
     float x;
     float y;
-    SkPaint* paint;
+    Paint* paint;
     uint16_t* glyphs;
     SkPoint* pos;
 };
 
 void SkiaCanvas::drawText(const uint16_t* text, int start, int count, int contextCount,
-        float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface) {
+        float x, float y, int bidiFlags, const Paint& paint, TypefaceImpl* typeface) {
     Layout layout;
     std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
     layout.doLayout(text, start, count, contextCount, css);
@@ -703,10 +704,10 @@
     uint16_t* glyphs = new uint16_t[nGlyphs];
     SkPoint* pos = new SkPoint[nGlyphs];
 
-    SkPaint paintCopy(paint);
+    Paint paintCopy(paint);
     x += MinikinUtils::xOffsetForTextAlign(&paintCopy, layout);
-    paintCopy.setTextAlign(SkPaint::kLeft_Align);
-    paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+    paintCopy.setTextAlign(Paint::kLeft_Align);
+    paintCopy.setTextEncoding(Paint::kGlyphID_TextEncoding);
 
     DrawTextFunctor f(layout, mCanvas, x, y, &paintCopy, glyphs, pos);
     MinikinUtils::forFontRun(layout, &paintCopy, f);
@@ -721,27 +722,27 @@
 #define kStdUnderline_Offset    (1.0f / 9.0f)
 #define kStdUnderline_Thickness (1.0f / 18.0f)
 
-void SkiaCanvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
+void SkiaCanvas::drawTextDecorations(float x, float y, float length, const Paint& paint) {
     uint32_t flags;
     SkDrawFilter* drawFilter = mCanvas->getDrawFilter();
     if (drawFilter) {
-        SkPaint paintCopy(paint);
+        Paint paintCopy(paint);
         drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
         flags = paintCopy.getFlags();
     } else {
         flags = paint.getFlags();
     }
-    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+    if (flags & (Paint::kUnderlineText_Flag | Paint::kStrikeThruText_Flag)) {
         SkScalar left = x;
         SkScalar right = x + length;
         float textSize = paint.getTextSize();
         float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
-        if (flags & SkPaint::kUnderlineText_Flag) {
+        if (flags & Paint::kUnderlineText_Flag) {
             SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
             SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
             mCanvas->drawRectCoords(left, top, right, bottom, paint);
         }
-        if (flags & SkPaint::kStrikeThruText_Flag) {
+        if (flags & Paint::kStrikeThruText_Flag) {
             SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
             SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
             mCanvas->drawRectCoords(left, top, right, bottom, paint);
@@ -750,7 +751,7 @@
 }
 
 void SkiaCanvas::drawPosText(const uint16_t* text, const float* positions, int count, int posCount,
-        const SkPaint& paint) {
+        const Paint& paint) {
     SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
     int indx;
     for (indx = 0; indx < posCount; indx++) {
@@ -758,15 +759,15 @@
         posPtr[indx].fY = positions[(indx << 1) + 1];
     }
 
-    SkPaint paintCopy(paint);
-    paintCopy.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+    Paint paintCopy(paint);
+    paintCopy.setTextEncoding(Paint::kUTF16_TextEncoding);
     mCanvas->drawPosText(text, count, posPtr, paintCopy);
 
     delete[] posPtr;
 }
 
 void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
-        float hOffset, float vOffset, const SkPaint& paint) {
+        float hOffset, float vOffset, const Paint& paint) {
     mCanvas->drawTextOnPathHV(glyphs, count, path, hOffset, vOffset, paint);
 }
 
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 46eccdd..377e71c 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -21,6 +21,7 @@
 #include "Canvas.h"
 #include "SkGraphics.h"
 #include "SkPorterDuff.h"
+#include "Paint.h"
 #include "TypefaceImpl.h"
 
 #include <minikin/Layout.h>
@@ -76,7 +77,7 @@
 
 static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
                       jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
-    SkPaint* paint  = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
     SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
     return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
 }
@@ -191,13 +192,13 @@
 }
 
 static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawPaint(*paint);
 }
 
 static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
                       jlong paintHandle) {
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawPoint(x, y, *paint);
 }
 
@@ -213,13 +214,13 @@
         return;
     }
 
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
 }
 
 static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
                      jfloat stopX, jfloat stopY, jlong paintHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
 }
 
@@ -235,38 +236,38 @@
         return;
     }
 
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
 }
 
 static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
                      jfloat right, jfloat bottom, jlong paintHandle) {
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
 }
 
 static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
                           jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
 }
 
 static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
                        jfloat radius, jlong paintHandle) {
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
 }
 
 static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
                      jfloat right, jfloat bottom, jlong paintHandle) {
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
 }
 
 static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
                     jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
                     jboolean useCenter, jlong paintHandle) {
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
                                        useCenter, *paint);
 }
@@ -274,7 +275,7 @@
 static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
                      jlong paintHandle) {
     const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawPath(*path, *paint);
 }
 
@@ -303,7 +304,7 @@
     }
 
     SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
                                            indices, indexCount, *paint);
 }
@@ -313,15 +314,15 @@
                        jint screenDensity, jint bitmapDensity) {
     Canvas* canvas = get_canvas(canvasHandle);
     const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
 
     if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
         if (screenDensity != 0 && screenDensity != bitmapDensity) {
-            SkPaint filteredPaint;
+            Paint filteredPaint;
             if (paint) {
                 filteredPaint = *paint;
             }
-            filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+            filteredPaint.setFilterLevel(Paint::kLow_FilterLevel);
             canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
         } else {
             canvas->drawBitmap(*bitmap, left, top, paint);
@@ -332,11 +333,11 @@
         canvas->translate(left, top);
         canvas->scale(scale, scale);
 
-        SkPaint filteredPaint;
+        Paint filteredPaint;
         if (paint) {
             filteredPaint = *paint;
         }
-        filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+        filteredPaint.setFilterLevel(Paint::kLow_FilterLevel);
 
         canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
         canvas->restore();
@@ -347,7 +348,7 @@
                              jlong matrixHandle, jlong paintHandle) {
     const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint);
 }
 
@@ -357,14 +358,14 @@
                            jlong paintHandle, jint screenDensity, jint bitmapDensity) {
     Canvas* canvas = get_canvas(canvasHandle);
     const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
 
     if (screenDensity != 0 && screenDensity != bitmapDensity) {
-        SkPaint filteredPaint;
+        Paint filteredPaint;
         if (paint) {
             filteredPaint = *paint;
         }
-        filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+        filteredPaint.setFilterLevel(Paint::kLow_FilterLevel);
         canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
                            dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
     } else {
@@ -391,7 +392,7 @@
         return;
     }
 
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
 }
 
@@ -403,7 +404,7 @@
     AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
 
     const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight,
                                              vertA.ptr(), colorA.ptr(), paint);
 }
@@ -411,7 +412,7 @@
 static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
                           jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
                           jlong paintHandle, jlong typefaceHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
     jchar* jchars = env->GetCharArrayElements(text, NULL);
     get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
@@ -422,7 +423,7 @@
 static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
                            jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
                            jlong paintHandle, jlong typefaceHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
     const int count = end - start;
     const jchar* jchars = env->GetStringChars(text, NULL);
@@ -434,7 +435,7 @@
 static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
                              jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
                              jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
     const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
@@ -448,7 +449,7 @@
                               jint start, jint end, jint contextStart, jint contextEnd,
                               jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
                               jlong typefaceHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
     int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
@@ -462,7 +463,7 @@
 
 static void drawPosTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
                              jint index, jint count, jfloatArray pos, jlong paintHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     jchar* jchars = text ? env->GetCharArrayElements(text, NULL) : NULL;
     float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
     int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
@@ -480,7 +481,7 @@
 
 static void drawPosTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
                               jfloatArray pos, jlong paintHandle) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     const jchar* jchars = text ? env->GetStringChars(text, NULL) : NULL;
     int byteLength = text ? env->GetStringLength(text) : 0;
     float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
@@ -499,7 +500,7 @@
 class DrawTextOnPathFunctor {
 public:
     DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
-                float vOffset, const SkPaint& paint, const SkPath& path)
+                float vOffset, const Paint& paint, const SkPath& path)
             : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
                 paint(paint), path(path) {
     }
@@ -517,14 +518,14 @@
     Canvas* canvas;
     float hOffset;
     float vOffset;
-    const SkPaint& paint;
+    const Paint& paint;
     const SkPath& path;
 };
 
 static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
                            const SkPath& path, float hOffset, float vOffset,
-                           const SkPaint& paint, TypefaceImpl* typeface) {
-    SkPaint paintCopy(paint);
+                           const Paint& paint, TypefaceImpl* typeface) {
+    Paint paintCopy(paint);
     Layout layout;
     std::string css = MinikinUtils::setLayoutProperties(&layout, &paintCopy, bidiFlags, typeface);
     layout.doLayout(text, 0, count, count, css);
@@ -533,7 +534,7 @@
     // Set align to left for drawing, as we don't want individual
     // glyphs centered or right-aligned; the offset above takes
     // care of all alignment.
-    paintCopy.setTextAlign(SkPaint::kLeft_Align);
+    paintCopy.setTextAlign(Paint::kLeft_Align);
 
     DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
     MinikinUtils::forFontRun(layout, &paintCopy, f);
@@ -544,7 +545,7 @@
                                 jfloat vOffset, jint bidiFlags, jlong paintHandle,
                                 jlong typefaceHandle) {
     SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
     jchar* jchars = env->GetCharArrayElements(text, NULL);
@@ -559,7 +560,7 @@
                                  jlong pathHandle, jfloat hOffset, jfloat vOffset,
                                  jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
     SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
     const jchar* jchars = env->GetStringChars(text, NULL);
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 760ed45..32cf286 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -79,26 +79,6 @@
     jmethodID setVendorInfo;
 } dhcpResultsFieldIds;
 
-static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
-{
-    int result;
-
-    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
-    result = ::ifc_enable(nameStr);
-    env->ReleaseStringUTFChars(ifname, nameStr);
-    return (jint)result;
-}
-
-static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname)
-{
-    int result;
-
-    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
-    result = ::ifc_disable(nameStr);
-    env->ReleaseStringUTFChars(ifname, nameStr);
-    return (jint)result;
-}
-
 static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
       jstring ifname, jint mask)
 {
@@ -280,9 +260,6 @@
  */
 static JNINativeMethod gNetworkUtilMethods[] = {
     /* name, signature, funcPtr */
-
-    { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
-    { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
     { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
     { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 8641e73..0a259aa 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -32,7 +32,6 @@
 #include <SkCanvas.h>
 #include <SkImageInfo.h>
 #include <SkMatrix.h>
-#include <SkPaint.h>
 #include <SkPorterDuff.h>
 #include <SkRegion.h>
 #include <SkScalerContext.h>
@@ -43,6 +42,7 @@
 #include <Rect.h>
 #include <RenderNode.h>
 #include <CanvasProperty.h>
+#include <Paint.h>
 
 #include <minikin/Layout.h>
 #include "MinikinSkia.h"
@@ -203,14 +203,14 @@
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr, jint saveFlags) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
 }
 
 static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong paintPtr, jint saveFlags) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
     return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
             paint, saveFlags);
@@ -349,7 +349,7 @@
     JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
 
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawBitmap(bitmap, left, top, paint);
 }
 
@@ -362,7 +362,7 @@
     JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
 
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
             dstLeft, dstTop, dstRight, dstBottom, paint);
 }
@@ -376,7 +376,7 @@
 
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawBitmap(bitmap, *matrix, paint);
 }
 
@@ -400,7 +400,7 @@
     }
 
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawBitmapData(bitmap, left, top, paint);
 
     // Note - bitmap isn't deleted as DisplayListRenderer owns it now
@@ -418,7 +418,7 @@
     jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
 
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
 
     if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
@@ -434,7 +434,7 @@
 
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
 }
 
@@ -449,7 +449,7 @@
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawRect(left, top, right, bottom, paint);
 }
 
@@ -457,14 +457,14 @@
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jfloat rx, jfloat ry, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
 }
 
 static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawCircle(x, y, radius, paint);
 }
 
@@ -482,7 +482,7 @@
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawOval(left, top, right, bottom, paint);
 }
 
@@ -490,7 +490,7 @@
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
 }
 
@@ -498,8 +498,8 @@
         jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
-    if (paint->getStyle() != SkPaint::kFill_Style ||
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
+    if (paint->getStyle() != Paint::kFill_Style ||
             (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) {
         SkRegion::Iterator it(*region);
         while (!it.done()) {
@@ -528,7 +528,7 @@
         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jfloat* storage = env->GetFloatArrayElements(points, NULL);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawPoints(storage + offset, count, paint);
     env->ReleaseFloatArrayElements(points, storage, 0);
 }
@@ -537,7 +537,7 @@
         jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawPath(path, paint);
 }
 
@@ -545,7 +545,7 @@
         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jfloat* storage = env->GetFloatArrayElements(points, NULL);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     renderer->drawLines(storage + offset, count, paint);
     env->ReleaseFloatArrayElements(points, storage, 0);
 }
@@ -573,7 +573,7 @@
 class RenderTextFunctor {
 public:
     RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
-                SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
+                Paint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
                 uirenderer::Rect& bounds)
             : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
             pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
@@ -593,7 +593,7 @@
     DisplayListRenderer* renderer;
     jfloat x;
     jfloat y;
-    SkPaint* paint;
+    Paint* paint;
     uint16_t* glyphs;
     float* pos;
     float totalAdvance;
@@ -601,7 +601,7 @@
 };
 
 static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
-    jfloat x, jfloat y, SkPaint* paint) {
+    jfloat x, jfloat y, Paint* paint) {
     size_t nGlyphs = layout->nGlyphs();
     float* pos = new float[nGlyphs * 2];
     uint16_t* glyphs = new uint16_t[nGlyphs];
@@ -618,7 +618,7 @@
 }
 
 static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
-        jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
+        jfloat x, jfloat y, int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
     Layout layout;
     std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
     layout.doLayout(text, 0, count, count, css);
@@ -629,7 +629,7 @@
 class RenderTextOnPathFunctor {
 public:
     RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
-                float vOffset, SkPaint* paint, SkPath* path)
+                float vOffset, Paint* paint, SkPath* path)
             : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
                 paint(paint), path(path) {
     }
@@ -647,19 +647,19 @@
     DisplayListRenderer* renderer;
     float hOffset;
     float vOffset;
-    SkPaint* paint;
+    Paint* paint;
     SkPath* path;
 };
 
 static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
-        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint,
+        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, Paint* paint,
         TypefaceImpl* typeface) {
     Layout layout;
     std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
     layout.doLayout(text, 0, count, count, css);
     hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
-    SkPaint::Align align = paint->getTextAlign();
-    paint->setTextAlign(SkPaint::kLeft_Align);
+    Paint::Align align = paint->getTextAlign();
+    paint->setTextAlign(Paint::kLeft_Align);
 
     RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
     MinikinUtils::forFontRun(layout, paint, f);
@@ -668,7 +668,7 @@
 
 static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
         jint start, jint count, jint contextCount, jfloat x, jfloat y,
-        int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
+        int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
     Layout layout;
     std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
     layout.doLayout(text, start, count, contextCount, css);
@@ -681,7 +681,7 @@
         jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
     renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
@@ -693,7 +693,7 @@
         jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
     renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
@@ -707,7 +707,7 @@
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
     renderTextOnPath(renderer, textArray + index, count, path,
@@ -722,7 +722,7 @@
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
     renderTextOnPath(renderer, textArray + start, end - start, path,
@@ -736,7 +736,7 @@
         jlong paintPtr, jlong typefacePtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
     int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
@@ -753,7 +753,7 @@
     const jchar* textArray = env->GetStringChars(text, NULL);
     jint count = end - start;
     jint contextCount = contextEnd - contextStart;
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
     int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 50edb76..aa674de 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -25,10 +25,10 @@
 
 #include <gui/GLConsumer.h>
 
+#include <Paint.h>
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkMatrix.h>
-#include <SkPaint.h>
 #include <SkXfermode.h>
 
 #include <DeferredLayerUpdater.h>
@@ -56,7 +56,7 @@
         jlong layerUpdaterPtr, jlong paintPtr) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
     if (layer) {
-        SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+        Paint* paint = reinterpret_cast<Paint*>(paintPtr);
         layer->setPaint(paint);
     }
 }
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 28473e0..1f3909a 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -26,6 +26,7 @@
 #include <Animator.h>
 #include <DisplayListRenderer.h>
 #include <RenderNode.h>
+#include <Paint.h>
 
 namespace android {
 
@@ -95,7 +96,7 @@
 
 static jboolean android_view_RenderNode_setLayerPaint(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jlong paintPtr) {
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
     return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
 }
 
@@ -152,6 +153,14 @@
     return true;
 }
 
+static jboolean android_view_RenderNode_setOutlineNone(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().mutableOutline().setNone();
+    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
+    return true;
+}
+
 static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
@@ -485,6 +494,7 @@
     { "nSetOutlineRoundRect",  "(JIIIIF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
     { "nSetOutlineConvexPath", "(JJ)Z",  (void*) android_view_RenderNode_setOutlineConvexPath },
     { "nSetOutlineEmpty",      "(J)Z",   (void*) android_view_RenderNode_setOutlineEmpty },
+    { "nSetOutlineNone",       "(J)Z",   (void*) android_view_RenderNode_setOutlineNone },
     { "nSetClipToOutline",     "(JZ)Z",  (void*) android_view_RenderNode_setClipToOutline },
     { "nSetRevealClip",        "(JZZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a2afb44..30629ad 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -894,7 +894,7 @@
         android:label="@string/permlab_nfc" />
 
     <!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
-        @hide -->
+         @hide -->
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="signature|system" />
@@ -905,10 +905,10 @@
         android:protectionLevel="signature|system" />
 
     <!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
-	@hide -->
+         @hide -->
     <permission android:name="android.permission.LOOP_RADIO"
-	android:permissionGroup="android.permission-group.NETWORK"
-	android:protectionLevel="signature|system" />
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="signature|system" />
 
     <!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
          @hide
@@ -1364,6 +1364,14 @@
         android:label="@string/permlab_getTasks"
         android:description="@string/permdesc_getTasks" />
 
+    <!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
+         @hide -->
+    <permission android:name="android.permission.START_TASKS_FROM_RECENTS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature|system"
+        android:label="@string/permlab_startTasksFromRecents"
+        android:description="@string/permdesc_startTasksFromRecents" />
+
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
          across the users on the device, using singleton services and
          user-targeted broadcasts.  This permission is not available to
@@ -2461,7 +2469,7 @@
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
         android:label="@string/permlab_pkgUsageStats"
         android:description="@string/permdesc_pkgUsageStats"
-        android:protectionLevel="signature|system" />
+        android:protectionLevel="signature|system|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <!-- @SystemApi Allows an application to collect battery statistics -->
@@ -2469,7 +2477,7 @@
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:label="@string/permlab_batteryStats"
         android:description="@string/permdesc_batteryStats"
-        android:protectionLevel="signature|system" />
+        android:protectionLevel="signature|system|development" />
 
     <!-- @SystemApi Allows an application to control the backup and restore process.
     <p>Not for use by third-party applications.
@@ -2848,7 +2856,7 @@
         <activity android:name="android.accounts.ChooseAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@android:style/Theme.Holo.Dialog"
+                android:theme="@android:style/Theme.Material.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -2856,14 +2864,14 @@
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@android:style/Theme.Holo.Dialog"
+                android:theme="@android:style/Theme.Material.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
                 android:excludeFromRecents="true"
-                android:theme="@android:style/Theme.Holo.Dialog"
+                android:theme="@android:style/Theme.Material.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -2871,14 +2879,14 @@
         <activity android:name="android.accounts.CantAddAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@android:style/Theme.Holo.Dialog.NoActionBar"
+                android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@android:style/Theme.Holo.DialogWhenLarge"
+                android:theme="@android:style/Theme.Material.DialogWhenLarge"
                 android:process=":ui">
         </activity>
 
diff --git a/core/res/res/drawable-hdpi/spinner_mtrl_am_alpha.9.png b/core/res/res/drawable-hdpi/spinner_mtrl_am_alpha.9.png
index de5819d..de7ac29 100644
--- a/core/res/res/drawable-hdpi/spinner_mtrl_am_alpha.9.png
+++ b/core/res/res/drawable-hdpi/spinner_mtrl_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_mtrl_am_alpha.9.png b/core/res/res/drawable-mdpi/spinner_mtrl_am_alpha.9.png
index f151bfb..bbf5928 100644
--- a/core/res/res/drawable-mdpi/spinner_mtrl_am_alpha.9.png
+++ b/core/res/res/drawable-mdpi/spinner_mtrl_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_mtrl_am_alpha.9.png b/core/res/res/drawable-xhdpi/spinner_mtrl_am_alpha.9.png
index c868ed1..d4bd169 100644
--- a/core/res/res/drawable-xhdpi/spinner_mtrl_am_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_mtrl_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_mtrl_am_alpha.9.png b/core/res/res/drawable-xxhdpi/spinner_mtrl_am_alpha.9.png
index 7cb1486..2e7bc12 100644
--- a/core/res/res/drawable-xxhdpi/spinner_mtrl_am_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_mtrl_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/spinner_mtrl_am_alpha.9.png b/core/res/res/drawable-xxxhdpi/spinner_mtrl_am_alpha.9.png
index 2ae7234..1086e9d 100644
--- a/core/res/res/drawable-xxxhdpi/spinner_mtrl_am_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/spinner_mtrl_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 55b79e8..2077543 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1386,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"للسماح لأحد التطبيقات بالالتزام بخدمة الوكيل المعتمد."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"التفاعل مع نظام التحديث والاسترداد"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"للسماح للتطبيق بالتفاعل مع نظام الاسترداد وتحديثات النظام."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"إنشاء جلسات عرض وسائط"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"للسماح لأحد التطبيقات بإنشاء جلسات عرض وسائط. ويُمكن لهذه الجلسات تمكين التطبيقات من التقاط محتويات مصورة وأخرى صوتية. ولا حاجة إليها مع التطبيقات العادية."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"المس مرتين للتحكم في التكبير/التصغير"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"تعذرت إضافة أداة."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"تنفيذ"</string>
@@ -1514,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"تعديل"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"تحذير استخدام البيانات"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"المس لعرض الاستخدام والإعدادات."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2-3 غيغابايت من البيانات المعطلة"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4 غيغابايت من البيانات المعطلة"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"البيانات الخلوية معطلة"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"‏بيانات Wi-Fi معطلة"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"تم بلوغ الحد المعين"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"‏تم تجاوز حد بيانات شبكات 2G-3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"‏تم تجاوز حد بيانات 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"تم تجاوز حد البيانات الخلوية"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"‏تم تجاوز حد بيانات شبكة Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> فوق الحد المعين."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"تم تقييد بيانات الخلفية"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 437f764..b87db9b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени на телефона ви. Това може да му позволи да изтрива или променя данните на браузъра. Забележка: Възможно е браузъри на трети страни или други приложения с възможности за сърфиране в мрежата да не могат да наложат ограниченията на разрешението."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"навиване на будилника"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"запис на гласови съобщения"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Разрешава на приложението да променя и премахва съобщения от входящата ви гласова поща."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"добавяне на гласова поща"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Разрешава на приложението да добавя съобщения към входящата ви гласова поща."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"четене на гласовата поща"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Разрешава на приложението да чете гласовите ви съобщения."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"промяна на разрешенията за местоположение в браузъра"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Разрешава на приложението да променя разрешенията на браузъра за местоположение. Злонамерените приложения могат да използват това, за да изпращат информация за местоположението до произволни уебсайтове."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"проверка на пакетите"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 7decead..81fee3a 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1748,7 +1748,7 @@
     <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"আপনি অ্যাপ-এ-লক করুন মোডে রয়েছেন৷"</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"অ্যাপ-এ-লক ব্যবহার করতে চান?"</string>
     <string name="lock_to_app_description" msgid="2800403592608529611">"লক-টু-অ্যাপ কোনো একক অ্যাপ্লিকেশানে প্রদর্শন লক করে।\n \nএটি থেকে বেরিয়ে যেতে ‘সাম্প্রতিকগুলি’ বোতাম স্পর্শ করে ধরে রাখুন।"</string>
-    <string name="lock_to_app_negative" msgid="2259143719362732728">"না, ধন্যবাদ"</string>
+    <string name="lock_to_app_negative" msgid="2259143719362732728">"না, থাক"</string>
     <string name="lock_to_app_positive" msgid="7085139175671313864">"চালু করুন"</string>
     <string name="lock_to_app_start" msgid="3074665051586318340">"অ্যাপ্লিকেশানে লক করা আছে"</string>
     <string name="lock_to_app_exit" msgid="8967089657201849300">"আর অ্যাপ্লিকেশানে লক করা নেই"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e8d3ecd..7e69339 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permet que l\'aplicació modifiqui l\'historial del navegador o els marcadors del telèfon. Això pot permetre que l\'aplicació esborri o modifiqui les dades del navegador. Nota: És possible que aquest permís no s\'apliqui a navegadors de tercers o a altres aplicacions amb capacitats de navegació web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"configuració d\'una alarma"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permet que l\'aplicació defineixi una alarma en una aplicació de despertador instal·lada. És possible que algunes aplicacions de despertador no incorporin aquesta funció."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"modificar correus de veu"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Permet que l\'aplicació modifiqui i suprimeixi missatges de la safata d\'entrada de la bústia de veu."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"afegeix bústia de veu"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet que l\'aplicació afegeixi missatges a la safata d\'entrada de la bústia de veu."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"accedir a la bústia de veu"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Permet que l\'aplicació accedeixi als correus de veu."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modifica els permisos d\'ubicació geogràfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permet que l\'aplicació modifiqui els permisos d\'ubicació geogràfica del navegador. Les aplicacions malicioses poden utilitzar-ho per enviar la informació d\'ubicació a llocs web arbitraris."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifica paquets"</string>
@@ -1745,7 +1741,7 @@
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> suprimit"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
     <string name="lock_to_app_toast" msgid="2126866321272822564">"Estàs en mode de bloqueig d\'aplicació. Per sortir-ne, toca i mantén premut el botó Recents."</string>
-    <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Estàs en el mode de bloqueig d\'aplicació."</string>
+    <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Estàs en el mode de Bloqueig d\'aplicació."</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"Vols fer servir la funció Bloqueig d\'aplicació?"</string>
     <string name="lock_to_app_description" msgid="2800403592608529611">"Amb Bloqueig d\'aplicació es bloqueja la pantalla en una única aplicació.\n\nPer sortir-ne, toca i mantén premut el botó Recents."</string>
     <string name="lock_to_app_negative" msgid="2259143719362732728">"NO, GRÀCIES"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 3d56653..01c2cef 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Umožňuje aplikaci upravit historii prohlížeče nebo záložky uložené v telefonu. Aplikace s tímto oprávněním může vymazat či pozměnit data prohlížeče. Poznámka: Pro prohlížeče třetí strany a jiné aplikace umožňující procházení webu toto oprávnění platit nemusí."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"nastavení budíku"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Umožňuje aplikaci nastavit budík v nainstalované aplikaci budík. Některé aplikace budík tuto funkci nemusí obsahovat."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"zápis do hlasové schránky"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Povoluje aplikaci upravit a odebrat zprávy z hlasové schránky."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"přidat hlasovou zprávu"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Umožňuje aplikaci přidávat zprávy do hlasové schránky."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"čtení hlasových zpráv"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Povoluje aplikaci číst hlasové zprávy."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"změna oprávnění prohlížeče poskytovat informace o zeměpisné poloze"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Umožňuje aplikaci upravit oprávnění funkce geolokace v prohlížeči. Škodlivé aplikace toho mohou využít k odeslání údajů o poloze na libovolné webové stránky."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ověřit balíčky"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikaci vázat se na službu zástupce důvěryhodnosti."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakce se systémem aktualizací a obnovení"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Umožňuje aplikaci interakci se systémem obnovení a s aktualizacemi systému."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Vytváření relací promítání médií"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Umožňuje aplikaci vytvářet relace promítání médií. Tyto relace mohou aplikacím umožnit zaznamenávat obsah obrazu a zvuku. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dvojitým dotykem můžete ovládat přiblížení"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget nelze přidat."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Přejít"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Upravit"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozornění na využití dat"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Informace o využití a nastavení"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Data 2G a 3G jsou vypnuta"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Data 4G jsou vypnuta"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mobilní data jsou vypnuta"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Data Wi-Fi jsou vypnuta"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Bylo dosaženo limitu"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Překročili jste limit dat 2G–3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Překročili jste limit dat 4G."</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Dosažen limit mobilních dat"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Datový limit Wi-Fi byl překročen"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> nad stanoveným limitem."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Přenos dat na pozadí je omezen"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 299e516..95bd92f 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Tillader, at appen kan ændre browserens historik eller de bogmærker, der er gemt på din telefon. Dette kan give appen tilladelse til at slette eller ændre browserdata. Bemærk! Denne tilladelse håndhæves muligvis ikke af tredjepartsbrowsere eller andre applikationer med websøgningsfunktioner."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"indstille en alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Tillader, at appen kan indstille en alarm i en installeret alarmapp. Nogle alarmapps har muligvis ikke denne funktion."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"skriv talebeskeder"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Tillader, at appen ændrer og fjerner beskeder fra indbakken for din telefonsvarer."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"tilføje telefonsvarer"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Tillader, at appen kan tilføje beskeder på din telefonsvarer."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"læs talebeskeder"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Tillader, at appen læser dine talebeskeder."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"skifte tilladelser til geografisk placering i Browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillader, at appen kan ændre browserens tilladelser angående geografisk placering. Ondsindede apps kan benytte dette til at sende oplysninger om placering til vilkårlige websites."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekræft pakker"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index db4ed5d..b373ecd 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Ermöglicht der App, den Browserverlauf und die Lesezeichen auf Ihrem Telefon zu ändern. Damit kann die App Browserdaten löschen und ändern. Hinweis: Diese Berechtigung kann nicht von Browsern von Drittanbietern oder anderen Apps mit Internetfunktionen erzwungen werden."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"Wecker stellen"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Ermöglicht der App, einen Alarm in einer installierten Wecker-App einzurichten. Einige Wecker-Apps implementieren diese Funktion möglicherweise nicht."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"Mailboxnachrichten ändern und entfernen"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Ermöglicht dieser App, Nachrichten im Posteingang Ihrer Mailbox zu ändern und zu entfernen"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"Mailbox-Nachrichten hinzufügen"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ermöglicht der App, Nachrichten zu Ihrem Mailbox-Posteingang hinzuzufügen"</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"Mailboxnachrichten abrufen"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Ermöglicht der App das Abrufen Ihrer Mailboxnachrichten"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Geolokalisierungsberechtigungen des Browsers ändern"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ermöglicht der App, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Apps können so Standortinformationen an beliebige Websites senden."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"Pakete überprüfen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5a69269..d3447b4 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Επιτρέπει στην εφαρμογή την τροποποίηση του ιστορικού του προγράμματος περιήγησης ή των σελιδοδεικτών που έχουν αποθηκευτεί στο τηλέφωνό σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να διαγράφει ή να τροποποιεί δεδομένα του προγράμματος περιήγησης. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί από τρίτα προγράμματα περιήγησης ή άλλες εφαρμογές με δυνατότητες περιήγησης ιστού."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ρύθμιση ξυπνητηριού"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Επιτρέπει στην εφαρμογή τη ρύθμιση μιας ειδοποίησης σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Ορισμένες εφαρμογές ξυπνητηριού ενδέχεται να μην μπορούν να ενσωματώσουν αυτήν τη λειτουργία."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"εγγραφή μηνυμάτων στον τηλεφωνητή"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Επιτρέπει στην εφαρμογή να τροποποιεί και να καταργεί τα μηνύματα από τα Εισερχόμενα του τηλεφωνητή σας."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"προσθήκη τηλεφωνητή"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Επιτρέπει στην εφαρμογή να προσθέτει μηνύματα στα εισερχόμενα του αυτόματου τηλεφωνητή σας."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"ανάγνωση μηνυμάτων στον τηλεφωνητή"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Επιτρέπει στην εφαρμογή να διαβάζει τα μηνύματα στον τηλεφωνητή σας."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"τροποποίηση δικαιωμάτων γεωγραφικής θέσης του Προγράμματος περιήγησης"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Επιτρέπει στην εφαρμογή την τροποποίηση των αδειών γεωτοποθεσίας του Προγράμματος περιήγησης. Τυχόν κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή πληροφοριών τοποθεσίας σε αυθαίρετους ιστότοπους."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"επαλήθευση πακέτων"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 33aaf80..0405f7c 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los marcadores del navegador almacenados en el teléfono. La aplicación puede utilizar este permiso para borrar o modificar datos del navegador. Nota: este permiso no pueden utilizarlo navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"establecer una alarma"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"editar los mensajes de voz"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Permite que la aplicación modifique y elimine mensajes de la bandeja de entrada del buzón de voz."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"añadir buzón de voz"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación añada mensajes a la bandeja de entrada del buzón de voz."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"consultar los mensajes de voz"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Permite que la aplicación consulte tus mensajes de voz."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que la aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones malintencionadas pueden usar este permiso para autorizar el envío de información sobre la ubicación a sitios web arbitrarios."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar paquetes"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index faf51bb..9c740c2 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Võimaldab rakendusel muuta telefoni salvestatud brauseri ajalugu või järjehoidjaid. See võimaldab rakendusel kustutada või muuta brauseri andmeid. Märkus: see luba ei pruugi jõustuda kolmanda osapoole brauserites või teistes veebisirvimisvõimega rakendustes."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"määrake äratus"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Võimaldab rakendusel seada installitud äratuskellarakenduses äratuse. Mõned äratuskellarakendused ei pruugi seda funktsiooni juurutada."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"kõneposti sõnumite kirjutamine"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Lubab rakendusel muuta ja kustutada kõneposti postkasti sõnumeid."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"lisa kõneposti"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Võimaldab rakendusel lisada sõnumeid teie kõneposti postkasti."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"kõneposti sõnumite lugemine"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Lubab rakendusel lugeda teie kõneposti sõnumeid."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Brauseri geolokatsiooniõiguste muutmine"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Võimaldab rakendusel muuta brauseri geolokatsiooniõigusi. Pahatahtlikud rakendused võivad seda kasutada asukohateabe saatmise lubamiseks suvalistele veebisaitidele."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakettide kinnitamine"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Lubab rakendusel ennast siduda usaldusväärse agendi teenusega."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Suhtlemine värskenduse ja taastesüsteemiga"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Lubab rakendusel suhelda taastesüsteemi ja süsteemivärskendustega."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Meediumi projitseerimise seansi loomine"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Lubab rakendusel luua meediumi projitsiooni seanssi. Need seansid võivad annda rakendustele võimaluse hõivata kuva- ja helisisu. Ei ole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Suumi juhtimiseks puudutage kaks korda"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidinat ei saanud lisada."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Mine"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Muuda"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Andmete kasutamise hoiatus"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Kasutuse/sätete vaat. puudutage."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G–3G andmeside on väljalülitatud"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G andmeside on väljalülitatud"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mob. andmeside väljalülitatud"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"WiFi andmeside väljalülitatud"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Limiit on täis"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G andmemahupiirang ületatud"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G andmemahupiirang ületatud"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Mob. andmeside limiit ületatud"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"WiFi-andmete piir on ületatud"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> üle määratud piirmäära."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Taustandmed on piiratud"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 67962fe..2bf1850 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Arakatzailearen historia edo telefonoan gordetako laster-markak aldatzeko baimena ematen die aplikazioei. Horrela, aplikazioak agian arakatzaile-datuak ezabatu edo aldatu ahal izango ditu. Oharra: baimen hori hirugarrenen arakatzaileek edo sarea arakatzeko gaitasuna eskaintzen duten bestelako aplikazioek aplika dezakete."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"alarmak ezartzea"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Instalatutako alarma batean alarmak ezartzea baimentzen die aplikazioei. Alarma-aplikazio batzuek agian ez dute eginbide hori inplementatuko."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"Idatzi ahots-mezuak"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Erantzungailuko sarrera-ontziko mezuak aldatzea eta kentzea baimentzen die aplikazioei."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"gehitu erantzungailua"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Erantzungailuko sarrera-ontzian mezuak gehitzea baimentzen die aplikazioei."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"Irakurri ahots-mezuak"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Erantzungailuko mezuak irakurtzea baimentzen die aplikazioei."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Aldatu arakatzailearen geokokapenaren baimenak"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Arakatzailearen geokokapenaren baimenak aldatzea baimentzen die aplikazioei. Aplikazio gaiztoek hori erabil dezakete kokapenari buruzko informazioa haiek hautatutako web-orrietara bidaltzeko."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"Egiaztatu paketeak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index e38baed..596daa8 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"به برنامه اجازه می‌دهد سابقه مرورگر یا نشانک‌های ذخیره شده در تلفن شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد داده‌های مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامه‌های دارای قابلیت مرور وب قابل اجرا نباشد."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"تنظیم یک هشدار"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"‏به برنامه اجازه می‎دهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامه‎های ساعت زنگدار نمی‎توانند این ویژگی را اعمال کنند."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"نوشتن پست‌های صوتی"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"به برنامه اجازه می‌دهد پیام‌ها را از صندوق ورودی پست صوتی شما تغییر داده و حذف کند."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"افزودن پست صوتی"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"به برنامه اجازه می‌دهد تا پیام‌ها را به صندوق دریافت پست صوتی شما اضافه کند."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"خواندن پست صوتی"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"به برنامه اجازه می‌دهد پست‌های صوتی‌تان را بخواند."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"تغییر مجوزهای مکان جغرافیایی مرورگر"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"‏به برنامه اجازه می‎دهد تا مجوزهای جغرافیایی مرورگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا اطلاعات موقعیت مکانی را به سایت‌های وب کتابخانه بفرستند."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"تأیید بسته‌ها"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"‏به یک برنامه کاربردی برای اتصال به یک سرویس trust agent اجازه می‌دهد."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"تعامل با سیستم به‌روزرسانی و بازیابی"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"به یک برنامه کاربردی اجازه می‌دهد با سیستم بازیابی و به‌روزرسانی‌های سیستم تعامل داشته باشد."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"ایجاد جلسات فرستادن رسانه"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"به برنامه اجازه می‌دهد جلسه‌های فرستادن رسانه ایجاد کند. این جلسات می‌توانند به برنامه این توانایی را بدهند که نمایشگر و محتوای صوتی را ضبط کند. هرگز نباید برای برنامه‌های عادی مورد نیاز باشد."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"دوبار لمس کنید تا بزرگنمایی کنترل شود"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"افزودن ابزارک انجام نشد."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"برو"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ویرایش"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"هشدار میزان استفاده از داده"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"برای مشاهده کاربرد و تنظیمات لمس کنید."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"‏داده 2G-3G خاموش است"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"‏داده 4G خاموش است"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"داده شبکه سلولی خاموش است"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"‏داده Wi-Fi خاموش است"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"به حد مجاز رسیده‌اید"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"‏اطلاعات 2G-3G بیش از حد مجاز است"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"‏بیش از حد مجاز 4G است"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"از حد مجاز شبکه سلولی فراتر رفتید"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"‏از محدوده مجاز داده‌های Wi-Fi بیشتر شد"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> از حد تعیین شده بیشتر شد."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"داده پس‌زمینه محدود شد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 4644c50..07a4c6e 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Antaa sovelluksen sitoutua luotettavaan tahoon."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Vuorovaikutus päivitys- ja palautusjärjestelmän kanssa"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Sallii sovelluksen vuorovaikutuksen palautusjärjestelmän ja järjestelmäpäivitysten kanssa."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Medialähetysistuntojen luominen"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Antaa sovelluksen luoda medialähetysistuntoja. Nämä istunnot antavat sovellusten tallentaa näyttö- ja äänisisältöä. Ei tavallisten sovellusten käyttöön."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Ohjaa zoomausta napauttamalla kahdesti"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widgetin lisääminen epäonnistui."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Siirry"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Muokkaa"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Tiedonsiirtovaroitus"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Näytä käyttö ja aset. koskettam."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G–3G-tiedonsiirto ei käytössä"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G-tiedonsiirto ei käytössä"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mobiilitiedonsiirto ei käytössä"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi-tiedonsiirto ei käytössä"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Raja saavutettu"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G-tiedonsiirtoraja ylitetty"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G-tiedonsiirtoraja ylitetty"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Mobiilitiedonsiirtoraja ylitetty"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fi-tiedonsiirtoraja ylitetty"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> yli asetetun rajan"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Rajoitettu taustatietojen käyttö"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 3896c16..eb7a45b 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite á aplicación modificar o historial ou os favoritos do navegador que están almacenados no teu teléfono. É posible que esta acción permita á aplicación borrar ou modificar os datos do navegador. Nota: É posible que este permiso non sexa executado por navegadores de terceiros ou outras aplicacións con funcionalidades de navegación web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"definir unha alarma"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite á aplicación definir unha alarma nunha aplicación de espertador instalada. É posible que algunhas aplicacións de espertador non implementen esta función."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"escribir correos de voz"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Permite á aplicación modificar e eliminar mensaxes da caixa de entrada do teu correo de voz."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"engadir correo de voz"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite á aplicación engadir mensaxes á caixa de entrada do teu correo de voz."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"ler correo de voz"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Permite á aplicación ler os teus correos de voz."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificar os permisos de xeolocalización do navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite á aplicación modificar os permisos de xeolocalización do navegador. É posible que as aplicacións maliciosas utilicen esta opción para permitir o envío de información de localización a sitios web arbitrarios."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar paquetes"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index a82e542..b2665e3 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ऐप्स  को आपके फ़ोन में संग्रहीत ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स  ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्‍यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्‍य ऐप्स  द्वारा लागू नहीं की जा सकती."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"अलार्म सेट करें"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ऐप्स को इंस्‍टॉल किए गए अलार्म घड़ी ऐप्स में अलार्म सेट करने देता है. हो सकता है कुछ अलार्म घड़ी ऐप्स में यह सुविधा न हो."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"ध्वनिमेल लिखें"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"ऐप्स को आपके ध्वनिमेल इनबॉक्स के संदेशों को बदलने और निकालने देती है."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्‍वनिमेल जोड़ें"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ऐप्स  को आपके ध्‍वनिमेल इनबॉक्‍स में संदेश जोड़ने देता है."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"ध्वनिमेल पढ़ें"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"ऐप्स को आपका ध्वनिमेल पढ़ने देती है."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउज़र भौगोलिक-स्थान अनुमतियों को बदलें"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ऐप्स को ब्राउज़र के भौगोलिक-स्‍थान की अनुमतियां संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स इसका उपयोग एकपक्षीय वेबसाइट को स्‍थान जानकारी भेजने में कर सकते हैं."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"पैकेज सत्‍यापि‍त करें"</string>
@@ -1752,7 +1748,7 @@
     <string name="lock_to_app_positive" msgid="7085139175671313864">"प्रारंभ करें"</string>
     <string name="lock_to_app_start" msgid="3074665051586318340">"ऐप्स-पर-लॉक किया गया"</string>
     <string name="lock_to_app_exit" msgid="8967089657201849300">"अब ऐप्स-पर-लॉक नहीं है"</string>
-    <string name="lock_to_app_use_screen_lock" msgid="1434584309048590886">"बाहर निकलने से पहले %1$s से पूछें"</string>
+    <string name="lock_to_app_use_screen_lock" msgid="1434584309048590886">"बाहर निकलने से पहले %1$s के लिए पूछें"</string>
     <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"पिन"</string>
     <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"पैटर्न अनलॉक करें"</string>
     <string name="lock_to_app_unlock_password" msgid="795224196583495868">"पासवर्ड"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 3d11cd3..2883233 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Aplikaciji omogućuje izmjenu povijesti i oznaka Preglednika pohranjenih na telefonu. To aplikaciji može omogućiti brisanje ili izmjenu podataka Preglednika. Napomena: tu dozvolu ne mogu primijeniti preglednici treće strane ili druge aplikacije s mogućnostima pregledavanja weba."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"postavljanje alarma"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Omogućuje aplikaciji postavljanje alarma na instaliranoj aplikaciji budilici. Neke aplikacije budilice možda neće primijeniti tu značajku."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"pisanje govorne pošte"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Omogućuje aplikaciji izmjenjivanje i uklanjanje poruka iz dolazne govorne pošte."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodaj govornu poštu"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Omogućuje aplikaciji da doda poruke u vašu govornu poštu."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"čitanje govorne pošte"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Omogućuje aplikaciji čitanje vaše govorne pošte."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"izmjena dozvola za geolociranje u pregledniku"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Omogućuje aplikaciji promjenu geolokacijskih dozvola preglednika. Zlonamjerne aplikacije mogu to upotrijebiti da bi dopustile slanje podataka o lokaciji nasumičnim web-lokacijama."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"provjeri pakete"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Omogućuje aplikaciji povezivanje s uslugom pouzdanog predstavnika."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcija s ažuriranjem i sustavom za oporavak"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Omogućuje aplikaciji interakciju sa sustavom za oporavak i ažuriranjima sustava."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Stvaranje sesija za projiciranje medija"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Omogućuje aplikaciji stvaranje sesija za projiciranje medija. Te sesije mogu omogućiti aplikaciji snimanje zaslona i audiosadržaja. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dodirnite dvaput za upravljanje zumiranjem"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget nije moguće dodati."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Idi"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Uredi"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozorenje o upotrebi podataka"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Dod. za prikaz upotrebe i post."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G-3G podaci isključeni"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G podaci isključeni"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mobilni podaci isključeni"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi podaci isključeni"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Ograničenje dosegnuto"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Prekoračeno ograničenje 2G-3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Prekoračeno je ograničenje 4G podataka"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Limit mobilnih podataka premašen"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Prekorač. Wi-Fi ogranič. pod."</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Veličina <xliff:g id="SIZE">%s</xliff:g> prelazi navedeno ograničenje."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Pozadinski podaci ograničeni"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c9570d2..4dfa0db 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a böngésző előzményeit vagy a telefonon tárolt könyvjelzőket. Az engedéllyel rendelkező alkalmazás törölheti vagy módosíthatja a böngésző adatait. Megjegyzés: előfordulhat, hogy ezt az engedélyt harmadik felek által üzemeltetett böngészők vagy egyéb böngészésre képes alkalmazások nem léptetik életbe."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ébresztés beállítása"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Lehetővé teszi az alkalmazás számára, hogy ébresztőt állítson be egy telepített ébresztőóra alkalmazásban. Egyes ilyen alkalmazásokban lehet, hogy nem működik ez a funkció."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"a hangüzenetek módosítása"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Lehetővé teszi az alkalmazás számára, hogy üzeneteket módosítson vagy távolítson el a bejövő hangpostafiókból."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"hangposta hozzáadása"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lehetővé teszi az alkalmazás számára, hogy üzeneteket adjon hozzá bejövő hangpostájához."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"a hangüzenetek olvasása"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Engedélyezi az alkalmazásnak a hangüzenetek olvasását."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"a böngésző helymeghatározási engedélyeinek módosítása"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a böngésző helymeghatározási engedélyeit. Rosszindulatú alkalmazások ezt arra használhatják, hogy a helyére vonatkozó információkat küldjenek tetszőleges webhelyeknek."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"csomagok ellenőrzése"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index cf020122..327d2ac 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Memungkinkan aplikasi mengubah riwayat atau bookmark Browser yang tersimpan dalam ponsel Anda. Izin ini memungkinkan aplikasi menghapus atau mengubah data Browser. Catatan: izin ini tidak dapat diberlakukan oleh browser pihak ketiga atau aplikasi lain dengan kemampuan menjelajahi web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"setel alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Mengizinkan apl menyetel alarm di apl jam alarm yang terpasang. Beberapa apl jam alarm mungkin tidak menerapkan fitur ini."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"tulis kotak pesan"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Memungkinkan aplikasi memodifikasi dan membuang pesan dari kotak masuk pesan suara Anda."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"tambahkan kotak pesan"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Mengizinkan apl menambahkan pesan ke kotak masuk untuk pesan suara Anda."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"baca kotak pesan"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Memungkinkan aplikasi membaca kotak pesan Anda."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"memodifikasi izin geolokasi Browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Mengizinkan apl memodifikasi izin geolokasi Browser. Apl berbahaya dapat menggunakan izin ini untuk memungkinkan pengiriman informasi lokasi ke sembarang situs web."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifikasi paket"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Mengizinkan aplikasi mengikat ke layanan agen kepercayaan."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan sistem pemulihan dan pembaruan"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Mengizinkan aplikasi berinteraksi dengan sistem pemulihan dan pembaruan sistem."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Membuat sesi proyeksi media"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Memungkinkan aplikasi membuat sesi proyeksi media. Sesi ini dapat memberikan kemampuan pada aplikasi untuk menangkap konten audio dan layar. Tidak diperlukan oleh aplikasi normal."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Sentuh dua kali untuk mengontrol perbesar/perkecil"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Tidak dapat menambahkan widget."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Buka"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edit"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Peringatan penggunaan data"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Sentuh utk mlht pnggnaan &amp; stln."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Data 2G-3G nonaktif"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Data 4G nonaktif"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Data seluler nonaktif"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Data Wi-Fi nonaktif"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Batas tercapai"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Batas data 2G-3G terlampaui"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Batas data 4G terlampaui"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Batas data seluler terlampaui"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Batas data Wi-Fi terlampaui"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> melebihi batas yang ditentukan."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Data latar belakang dibatasi"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 270fb8c..c76d4d79 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Leyfir forriti að breyta vafraferlinum eða bókamerkjum sem vistuð eru í símanum. Þetta getur gert forritinu kleift að eyða eða breyta vafragögnum. Athugaðu: Ekki er víst að þessi heimild sé virt í vöfrum frá þriðja aðila eða öðrum forritum með vafraeiginleika."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"stilla vekjara"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Leyfir forriti að stilla vekjara á uppsettri vekjaraklukku. Verið getur að sum vekjaraklukkuforrit séu ekki búin þessum eiginleika."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"skrifa talhólfsskilaboð"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Leyfir forritinu að breyta og fjarlægja skilaboð úr talhólfinu."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"bæta við talhólfi"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Leyfir forriti að bæta skilaboðum við talhólfið þitt."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"lesa talhólfsskilaboð"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Leyfir forritinu að lesa talhólfsskilaboðin þín."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"breyta staðsetningarheimildum vafrans"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Leyfir forriti að breyta heimildum vafrans fyrir landfræðilega staðsetningu. Spilliforrit geta notað þetta til að leyfa sendingu staðsetningarupplýsinga á vafasöm vefsvæði."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"staðfesta pakka"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1241118..bf821f5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Consente all\'applicazione di modificare la cronologia o i segnalibri del Browser memorizzati sul telefono. Ciò potrebbe consentire all\'applicazione di cancellare o modificare i dati del Browser. Nota. È possibile che questa autorizzazione non sia applicabile da browser di terze parti o altre applicazioni con funzionalità di navigazione web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"impostazione sveglia"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Consente all\'applicazione di impostare una sveglia in un\'applicazione sveglia installata. È possibile che alcune applicazioni sveglia non possano implementare questa funzione."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"scrivi messaggi vocali"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Consente all\'app di modificare e rimuovere messaggi dalla segreteria."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"aggiunta di un messaggio vocale"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Consente all\'applicazione di aggiungere messaggi alla casella della segreteria."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"leggi messaggi vocali"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Consente all\'app di leggere i messaggi vocali."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modifica delle autorizzazioni di localizzazione geografica del browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Consente all\'applicazione di modificare le autorizzazioni di geolocalizzazione del Browser. Le applicazioni dannose potrebbero farne uso per consentire l\'invio di informazioni sulla posizione a siti web arbitrari."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifica dei pacchetti"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 73b9f94..00be975 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"携帯端末に保存されているブラウザの履歴やブックマークの変更をアプリに許可します。これにより、アプリがブラウザデータを消去または変更できるようになる可能性があります。注: この許可は、サードパーティブラウザまたはウェブブラウジング機能を備えたその他のアプリでは適用されない場合があります。"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"アラームの設定"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"インストール済みアラームアプリのアラームを設定することをアプリに許可します。この機能が実装されていないアラームアプリもあります。"</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"ボイスメールの書き込み"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"ボイスメール受信トレイからメッセージを修正、削除することをアプリに許可します。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ボイスメールの追加"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ボイスメール受信トレイにメッセージを追加することをアプリに許可します。"</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"ボイスメールの読み取り"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"ボイスメールの読み取りをアプリに許可します。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ブラウザの現在地情報に対する権限の変更"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ブラウザの現在地情報に対する権限の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、任意のウェブサイトに現在地情報が送信される恐れがあります。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"パッケージのベリファイ"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"信頼できるエージェントサービスにバインドすることをアプリに許可します。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"アップデートと回復システムへのアクセス"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"回復システムとシステムアップデートへのアクセスをアプリに許可します。"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"メディアプロジェクションセッションの作成"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"メディアプロジェクションセッションの作成をアプリに許可します。これらのセッションでは、アプリがディスプレイ/オーディオコンテンツをキャプチャできます。通常のアプリでは不要です。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ダブルタップでズームコントロール"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ウィジェットを追加できませんでした。"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"移動"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編集"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"データ使用の警告"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"タップして使用状況と設定を表示します。"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G~3Gデータが無効になりました"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4Gデータが無効になりました"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"モバイルデータが無効になりました"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fiデータが無効になりました"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"上限に達しました"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G~3Gデータの上限を超えました"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4Gデータの上限を超えました"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"モバイルデータの上限を超えました"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fiデータの上限を超えました"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"指定した上限を<xliff:g id="SIZE">%s</xliff:g>超えました。"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"バックグラウンドデータに上限あり"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 342887e..86d6e66 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1752,25 +1752,16 @@
     <string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
-    <skip />
+    <string name="lock_to_app_toast" msgid="2126866321272822564">"თქვენ იმყოფებით აპის ფიქსაციის რეჟიმში. გამოსასვლელად, დააჭირეთ და დააყოვნეთ ბოლო აპების ღილაკზე"</string>
     <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"თქვენ იმყოფებით აპის ფიქსაციის რეჟიმში."</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"გსურთ „აპში ჩაკეტვის“ გამოყენება?"</string>
-    <!-- no translation found for lock_to_app_description (2800403592608529611) -->
-    <skip />
-    <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
-    <skip />
+    <string name="lock_to_app_description" msgid="2800403592608529611">"„აპში ჩაკეტვა“ კეტავს ეკრანს ერთ აპში.\n\nგასასვლელად დააჭირეთ და არ აუშვათ ღილაკს „ბოლო აპები“."</string>
+    <string name="lock_to_app_negative" msgid="2259143719362732728">"არა, გმადლობთ"</string>
     <string name="lock_to_app_positive" msgid="7085139175671313864">"დაწყება"</string>
-    <!-- no translation found for lock_to_app_start (3074665051586318340) -->
-    <skip />
-    <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
-    <skip />
-    <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
-    <skip />
+    <string name="lock_to_app_start" msgid="3074665051586318340">"აპზე დაფიქსირებული"</string>
+    <string name="lock_to_app_exit" msgid="8967089657201849300">"აპზე დაფიქსირებული აღარ არის"</string>
+    <string name="lock_to_app_use_screen_lock" msgid="1434584309048590886">"გასვლამდე %1$s-ის მოთხოვნა"</string>
+    <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN-კოდი"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"განბლოკვის ნიმუში"</string>
+    <string name="lock_to_app_unlock_password" msgid="795224196583495868">"პაროლი"</string>
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 7cbaca8..ba6c0ac 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1392,10 +1392,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"ឲ្យ​កម្មវិធី​ភ្ជាប់​សេវាកម្ម​ភ្នាក់ងារ​ដែល​ទុក​ចិត្ត។"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"អន្តរកម្ម​ជា​មួយ​បច្ចុប្បន្នភាព និង​ប្រព័ន្ធ​សង្គ្រោះ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ឲ្យ​កម្មវិធី​មាន​អន្តរកម្ម​ជា​មួយ​ប្រព័ន្ធ​សង្គ្រោះ និង​បច្ចុប្បន្នភាព​ប្រព័ន្ធ។"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"បង្កើត​សម័យ​គម្រោង​មេឌៀ"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"ឲ្យ​កម្មវិធី​បង្កើត​សម័យ​គម្រោង​មេឌៀ។ សម័យ​ទាំងនេះ​​អាច​​ធ្វើឲ្យ​កម្មវិធី​មានលទ្ធភាព​ចាប់​យក​​មាតិកា​​នៃ​ការ​បង្ហាញ និង​សំឡេង។ មិន​គួរ​ចាំបាច់​​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ប៉ះ​ពីរ​ដង ​​ដើម្បី​គ្រប់គ្រង​ការ​ពង្រីក"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"មិន​អាច​បន្ថែម​ធាតុ​ក្រាហ្វិក។"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string>
@@ -1520,20 +1518,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល​"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"ការព្រមាន​ប្រើ​ទិន្នន័យ"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"ប៉ះ ដើម្បី​មើល​ការ​ប្រើ និង​ការ​កំណត់។"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"ទិន្នន័យ 2G-3G បាន​បិទ"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"ទិន្នន័យ 4G បាន​បិទ"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"ទិន្នន័យ​ចល័ត​បាន​បិទ"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"ទិន្នន័យ​វ៉ាយហ្វាយ​បាន​បិទ"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"បាន​ដល់​ដែន​កំណត់"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"លើស​ដែន​កំណត់​ទិន្នន័យ 2G​-3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"បាន​លើស​ដែន​កំណត់​ទិន្នន័យ 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"បាន​លើស​ដែន​កំណត់​ទិន្នន័យ​ចល័ត"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"លើស​ដែន​កំណត់​ទិន្នន័យ​វ៉ាយហ្វាយ"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> លើ​ដែន​កំណត់​បាន​បញ្ជាក់។"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"បាន​ដាក់​កម្រិត​ទិន្នន័យ​ផ្ទៃ​ខាង​ក្រោយ"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index c9e0519..d6143e1 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ನಿಮ್ಮ ಫೋನ್‍‍‍ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ಬ್ರೌಸರ್‍‍ನ ಇತಿಹಾಸ ಅಥವಾ ಬುಕ್‌ಮಾರ್ಕ್ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಇದು ಬ್ರೌಸರ್‍‍ನ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ಅಥವಾ ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸಿಕೊಡಬಹುದು. ಗಮನಿಸಿ: ಈ ಅನುಮತಿಯನ್ನು ವೆಬ್ ಬ್ರೌಸಿಂಗ್ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಹೊಂದಿರುವ ಮೂರನೇ-ವ್ಯಕ್ತಿ ಬ್ರೌಸರ್‍‍ಗಳು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳ ಮೂಲಕ ಜಾರಿಗೊಳಿಸಲಾಗುವುದಿಲ್ಲ."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ಅಲಾರಮ್ ಹೊಂದಿಸಿ"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ಸ್ಥಾಪಿಸಲಾದ ಅಲಾರಾಂ ಗಡಿಯಾರ ಅಪ್ಲಿಕೇಶನ್‌ನಲ್ಲಿ ಅಲಾರಾಂ ಹೊಂದಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಕೆಲವು ಅಲಾರಾಂ ಗಡಿಯಾರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸದಿರಬಹುದು."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"ಧ್ವನಿಮೇಲ್‌ಗಳನ್ನು ಬರೆಯಿರಿ"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"ನಿಮ್ಮ ಧ್ವನಿಮೇಲ್ ಇನ್‌ಬಾಕ್ಸ್‌ನಿಂದ ಸಂದೇಶಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಮತ್ತು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ಧ್ವನಿಮೇಲ್ ಸೇರಿಸಿ"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ನಿಮ್ಮ ದ್ವನಿಮೇಲ್‌ ಇನ್‌‌ಬಾಕ್ಸ್‌‌ಗೆ ಸಂದೇಶಗಳನ್ನು ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"ಧ್ವನಿಮೇಲ್ ಓದಿ"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"ನಿಮ್ಮ ಎಲ್ಲಾ ಧ್ವನಿಮೇಲ್‌ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ಬ್ರೌಸರ್‌ ಜಿಯೋಲೊಕೇಶನ್‌‌ ಅನುಮತಿಗಳನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ಬ್ರೌಸರ್‌ನ ಜಿಯೋಲೊಕೇಶನ್ ಅನುಮತಿಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಅನಿರ್ಬಂಧಿತ ವೆಬ್ ಸೈಟ್‌ಗಳಿಗೆ ಸ್ಥಳ ಮಾಹಿತಿ ಕಳುಹಿಸುವುದನ್ನು ಅನುಮತಿಸಲು ಇದನ್ನು ಬಳಸಬಹುದು."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ಪ್ಯಾಕೇಜ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1afab47..7b9c05a 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"애플리케이션이 Trust Agent 서비스에 바인딩할 수 있도록 허용합니다."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"업데이트 및 복구 시스템과 상호작용"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"애플리케이션이 복구 시스템 및 시스템 업데이트와 상호작용할 수 있도록 허용합니다."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"미디어 프로젝션 세션 만들기"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"애플리케이션이 미디어 프로젝션 세션을 만드는 것을 허용합니다. 이 세션은 애플리케이션에 디스플레이 및 오디오 컨텐츠를 캡처하는 기능을 제공할 수 있습니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"확대/축소하려면 두 번 터치하세요."</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"위젯을 추가할 수 없습니다."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"이동"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"수정"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"데이터 사용 경고"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"사용량 및 설정을 보려면 터치하세요."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G-3G 데이터 사용 중지됨"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G 데이터 사용 중지됨"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"이동통신 데이터 사용 중지됨"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi 데이터 사용 중지됨"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"한도 도달"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G - 3G 데이터 제한 초과됨"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4GB의 데이터 제한 초과됨"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"이동통신 데이터 한도 초과"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fi 데이터 한도 초과됨"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> - 지정된 한도 초과"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"백그라운드 데이터 사용이 제한됨"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index cdc2b47..5eb55c1 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Leidžiama programai keisti naršyklės istoriją ar žymes, išsaugotas telefone. Dėl to programai gali būti leidžiama ištrinti ar keisti naršyklės duomenis. Pastaba: šis leidimas nesuteikiamas trečiosios šalies naršyklėms ar kitoms programoms, kuriomis galima naršyti žiniatinklį."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"nustatyti pavojaus signalą"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Leidžiama programai nustatyti signalą įdiegtoje žadintuvo programoje. Kai kuriose žadintuvo programose ši funkcija gali nebūti nevykdoma."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"rašyti balso pašto pranešimus"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Programai leidžiama keisti ir šalinti pranešimus iš balso pašto gautųjų."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"pridėti balso pašto pranešimų"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Leidžia programai pridėti pranešimų prie jūsų balso pašto gautųjų."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"skaityti balso pašto pranešimus"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Programai leidžiama skaityti balso pašto pranešimus."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"keisti naršyklės geografinės vietos leidimus"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Leidžiama programai keisti naršyklės geografinės vietos leidimus. Kenkėjiškos programos gali tai naudoti, kad leistų siųsti vietos informaciją abejotinoms svetainėms."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"patikrinti paketus"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Programai leidžiama susisaistyti su „trust agent“ paslauga."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Sąveikauti su naujiniu ir atkūrimo sistema"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Programai leidžiama sąveikauti su atkūrimo sistema ir sistemos naujiniais."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Kurti medijos projekcijų seansus"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Programai leidžiama kurti medijos projekcijų seansus. Sukūrusios šiuos seansus, programos gali fiksuoti vaizdo ir garso turinį. To niekada neturėtų prireikti naudojant įprastas programas."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dukart palieskite, kad valdytumėte mastelio keitimą"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nepavyko pridėti."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Pradėti"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Redaguoti"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Įspėjimas dėl duomenų naudojimo"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Palieskite ir žr. naud. ir nust."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G–3G duomenys išjungti"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G duomenys išjungti"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mobil. ryšio duomenys išjungti"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"„Wi-Fi“ duomenys išjungti"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Pasiektas limitas"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Viršyta 2G–3G duomenų riba"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Viršyta 4G duomenų riba"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Viršytas mobil. duom. limitas"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Viršytas „Wi-Fi“ duomenų aprib."</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> viršyta nurodyta riba."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Apriboti foniniai duomenys"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 66a4fad..f005960 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Ļauj lietotnei mainīt tālrunī saglabāto pārlūkprogrammas vēsturi vai grāmatzīmes. Tas var ļaut lietotnei dzēst vai pārveidot pārlūkprogrammas datus. Piezīme: šo atļauju nevar piemērot trešo pušu pārlūkprogrammas vai citas lietojumprogrammas ar tīmekļa pārlūkošanas iespējām."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"iestatīt modinātāju"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Ļauj lietotnei iestatīt signālu instalētajā modinātājpulksteņa lietotnē. Dažās modinātājpulksteņu lietotnēs šo funkciju, iespējams, nevar ieviest."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"rakstīt balss pasta ziņojumus"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Ļauj lietotnei rediģēt un noņemt ziņojumus no jūsu balss pasta iesūtnes."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"pievienot balss pastu"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ļauj lietotnei pievienot ziņojumus jūsu balss pasta iesūtnei."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"lasīt balss pastu"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Ļauj lietotnei lasīt jūsu balss pasta ziņojumu."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ļauj lietotnei modificēt pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas. Ļaunprātīgas lietotnes to var izmantot, lai atļautu atrašanās vietas informācijas sūtīšanu uz citām vietnēm."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakotņu verificēšana"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ļauj lietojumprogrammai izveidot savienojumu ar uzticamības pārbaudes pakalpojumu."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Mijiedarbošanās ar atjauninājumu un atkopšanas sistēmu"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ļauj lietojumprogrammai mijiedarboties ar atkopšanas sistēmu un sistēmas atjauninājumiem."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Izveidot satura projekcijas sesijas"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Ļauj lietojumprogrammai izveidot satura projekcijas sesijas. Šīs sesijas var atļaut lietojumprogrammām uzņemt ekrāna un skaņas saturu. Parastām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Pieskarieties divreiz, lai kontrolētu tālummaiņu."</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nevarēja pievienot logrīku."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Doties uz"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Rediģēt"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Datu izmantošanas brīdinājums"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Piesk., lai sk. lietoš. un iest."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G–3G dati ir atslēgti"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G dati ir atslēgti"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mobilie dati ir atslēgti"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi dati ir atslēgti"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Sasniegts ierobežojums"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G datu ierobež. pārsniegts"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G datu limits pārsniegts"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Pārsniegts mob. datu ierobežojums"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fi datu ierobež. pārsniegts"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> virs norādītā ierobežojuma."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Fona dati ir ierobežoti."</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 5636655..d49a824 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Овозможува апликацијата да ја менува историјата на прелистувачот или обележувачите зачувани во вашиот телефон. Ова може да овозможи апликацијата да избрише или да измени податоци за прелистувач. Напомена: оваа дозвола не може да ја наметнат прелистувачи на трети лица или други апликации со способности за прелистување на интернет."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"постави аларм"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Дозволува апликацијата да постави аларм во инсталираната апликација со будилник. Некои апликации со будилници може да не ја применуваат оваа можност."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"пишувај говорна пошта"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Ѝ дозволува на апликацијата да ги менува и да ги отстранува пораките од приемното сандаче за говорна пошта."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"додај говорна пошта"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозволува апликацијата да додава пораки во сандачето за гласовна пошта."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"читај говорна пошта"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Ѝ дозволува на апликацијата да ги чита говорните пораки."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"измени дозволи за геолокација на прелистувач"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Дозволува апликацијата да ги измени дозволите за геолокација на прелистувачот. Злонамерните апликации може да го искористат тоа за да се дозволи испраќање информации за локација до случајни веб-локации."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"потврди пакети"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозволува апликацијата да се поврзе со услуга за агенти за доверба."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Комуницирај со системот за обновување и ажурирање"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Овозможува апликацијата да комуницира со системот за обновување и ажурирање."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Создади сесии за проектирање на медиуми"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Дозволува апликацијата да создава сесии за проектирање на медиуми. Овие сесии им обезбедуваат можност на апликациите да снимаат екранска и аудиосодржина. Не би требало да се користи кај вообичаени апликации."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Допрете двапати за регулирање на зумирањето"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не можеше да се додаде виџет."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Оди"</string>
@@ -1520,20 +1514,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Уреди"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Предупредување за користење податоци"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Допри за да видиш употреба и подесувања."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Податоците 2G-3G се исклучени"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Податоците 4G се исклучени"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Мобилните податоци се исклучени"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Подат. преку Wi-Fi се исклучени"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Го достигнавте лимитот"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Надминат лимит од 2G-3G податоци"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Надминат лимит од 4G податоци"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Лимитот за моб. подат. е надминат"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Надминат лимит на Wi-Fi податоци"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> над назначената граница."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Подат. од заднина се ограничени"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 4760788..9115ba2 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"നിങ്ങളുടെ ഫോണിൽ സംഭരിച്ചിരിക്കുന്ന ബ്രൗസറിന്റെ ചരിത്രമോ ബുക്ക്‌മാർക്കുകളോ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് ബ്രൗസർ ഡാറ്റ മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്. ശ്രദ്ധിക്കുക: ഈ അനുമതി മൂന്നാം കക്ഷി ബ്രൗസറുകളോ വെബ് ബ്രൗസിംഗ് കഴിവുകളുള്ള മറ്റ് അപ്ലിക്കേഷനുകളോ നടപ്പിലാക്കാനിടയില്ല."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ഒരു അലാറം സജ്ജീകരിക്കുക"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ഒരു ഇൻസ്റ്റാളുചെയ്‌ത അലാറം ക്ലോക്ക് അപ്ലിക്കേഷനിൽ അലാറം സജ്ജീകരിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ചില അലാറം ക്ലോക്ക് അപ്ലിക്കേഷനുകൾ ഈ സവിശേഷത നടപ്പിലാക്കാതിരുന്നേക്കാം."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"വോയ്‌സ്‌മെയിലുകൾ റൈറ്റുചെയ്യുക"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"നിങ്ങളുടെ വോയ്‌സ്മെയിൽ ഇൻബോക്‌സിൽ നിന്നും സന്ദേശങ്ങൾ പരിഷ്ക്കരിക്കാനും നീക്കംചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"വോയ്‌സ് മെയിൽ ചേർക്കുക"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"നിങ്ങളുടെ വോയ്‌സ്മെയിൽ ഇൻബോക്‌സിലേക്ക് സന്ദേശങ്ങൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"വോയ്‌സ്‌മെയിൽ റീഡുചെയ്യുക"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"നിങ്ങളുടെ വോയ്‌സ്‌മെയിലുകൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ബ്രൗസർ ജിയോലൊക്കേഷൻ അനുമതികൾ പരിഷ്‌ക്കരിക്കുക"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ബ്രൗസറിന്റെ ജിയോലൊക്കേഷൻ അനുമതികളെ പരിഷ്‌ക്കരിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അനിയന്ത്രിതമായ വെബ്‌സൈറ്റുകളിലേക്ക് ലൊക്കേഷൻ വിവരം അയയ്ക്കാൻ അനുവദിക്കുന്നതിന് ദോഷകരമായ അപ്ലിക്കേഷനുകൾ ഇത് ഉപയോഗിച്ചേക്കാം."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"പാക്കേജുകൾ പരിശോധിച്ചുറപ്പിക്കുക"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 73ff335..30e0efb 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"आपल्या फोनवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅप ला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅप ला अनुमती देते. टीप: ही परवानगी तृतीय पक्ष ब्राउझरद्वारे किंवा वेब ब्राउझिंग क्षमतांसह अन्य अनुप्रयोगांद्वारे अंमलबजावणी करण्याची टीप देऊ शकते."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"अलार्म सेट करा"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"स्थापित केलेल्या अलार्म घड्याळ अॅपमध्ये अलार्म सेट करण्यासाठी अॅप ला अनुमती देते. काही अलार्म घड्याळ अॅप्स हे वैशिष्ट्य लागू करू शकत नाहीत."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"व्हॉइसमेल लिहा"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"आपल्या व्हॉइसमेल इनबॉक्समधील संदेश सुधारित करण्यासाठी आणि ते काढण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"व्हॉइसमेल जोडा"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"आपल्या व्हॉइसमेल इनबॉक्समध्ये संदेश जोडण्यासाठी अॅप ला अनुमती देते."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"व्हॉइसमेल वाचा"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"आपले व्‍हॉइसमेल वाचण्‍याची अ‍ॅपला अनुमती देते."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउझर भौगोलिक स्थान परवानग्या सुधारित करा"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ब्राउझरच्या भौगोलिक स्थान परवानग्या सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स यादृच्छिक वेबसाइटवर स्थान माहिती पाठविण्यास अनुमती देण्यासाठी याचा वापर करू शकतात."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"पॅकेज सत्‍यापित करा"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 5fedab5..fc823ee 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1752,25 +1752,16 @@
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dipadamkan"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
-    <skip />
+    <string name="lock_to_app_toast" msgid="2126866321272822564">"Anda berada dalam mod kunci ke apl. Untuk keluar, sentuh dan tahan butang Terbaru"</string>
     <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Anda berada dalam mod Kunci ke Apl."</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"Gunakan kunci ke apl?"</string>
-    <!-- no translation found for lock_to_app_description (2800403592608529611) -->
-    <skip />
-    <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
-    <skip />
+    <string name="lock_to_app_description" msgid="2800403592608529611">"Kunci dalam apl mengunci paparan dalam apl tunggal.\n\nUntuk keluar, sentuh dan tahan butang Terbaru."</string>
+    <string name="lock_to_app_negative" msgid="2259143719362732728">"TIDAK, TERIMA KASIH"</string>
     <string name="lock_to_app_positive" msgid="7085139175671313864">"MULA"</string>
-    <!-- no translation found for lock_to_app_start (3074665051586318340) -->
-    <skip />
-    <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
-    <skip />
-    <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
-    <skip />
+    <string name="lock_to_app_start" msgid="3074665051586318340">"Dikunci ke apl"</string>
+    <string name="lock_to_app_exit" msgid="8967089657201849300">"Tidak lagi dikunci ke apl"</string>
+    <string name="lock_to_app_use_screen_lock" msgid="1434584309048590886">"Minta %1$s sebelum keluar"</string>
+    <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"corak buka kunci"</string>
+    <string name="lock_to_app_unlock_password" msgid="795224196583495868">"kata laluan"</string>
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index f3fc7cc..46b536a 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"အပလီကေးရှင်းအား ဘရောင်ဇာမှ မှတ်တမ်း သို့ မှတ်သားမှု အမှတ်များအား ပြင်ဆင်ခွင့် ပေးခြင်း။ အပလီကေးရှင်းမှ ဘရောင်ဇာ မှတ်တမ်းများကို ဖျက်ပစ်ခွင့် သို့ ပြင်ဆင်ခွင့် ရှိပါမည်။ မှတ်ချက်။ ဒီခွင့်ပြုချက်ကို တတိယပါတီ ဘရောင်ဇာများ၊ တခြား အပလီကေးရှင်းများမှ သုံးမည် မဟုတ်ပါ။"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"နှိုးစက်သတ်မှတ်ရန်"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"appအား တပ်ဆင်ထားသည့် နှိုးစက်နာရီ app ထဲတွင် နှိုးစက်ကို သတ်မှတ်ခွင့် ပြုသည်။ အချို့ နှိုးစက် appများက ထိုအင်္ဂါရပ်ကို ပြီးမြောက်အောင် မလုပ်နိုင်ကြပါ။"</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"အသံမေးလ်ကို ရေးရန်"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"appအား သင်၏ အသံမေးလ် ဝင်စာများကို မွမ်းမံခွင့် နှင့် ဖယ်ရှားခွင့် ပြုသည်။"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"အသံစာပို့စနစ်အားထည့်ရန်"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"appအား သင့် အသံမေးလ် ဝင်စာသို့ စာများကို ထည့်ခွင့် ပြုသည်။"</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"အသံမေးလ်ကို  ဖတ်ရန်"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"appအား သင်၏ အသံမေးလ်များကို ဖတ်ခွင့် ပြုရန်"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ဘရောင်ဇာ ဘူမိဇုန်သတ်မှတ်မှု ခွင့်ပြုချက်များကို မွမ်းမံခြင်း"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"appအား ဘရောင်ဇာ၏ ဘူမိဇုန်သတ်မှတ်ရေး ခွင့်ပြုချက်များကို မွမ်းမံခွင့် ပြုသည်။ ကြံဖန် appများက ၎င်းကို အသုံးချပြီး လိုရာ ဝက်ဘ်ဆိုက်များသို့ တည်နေရာ အချက်အလက် ပို့မှုကို လုပ်နိုင်သည်။"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"packages များကိုအတည်ပြုစိစစ်ခြင်း"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 502e0b8..d8efcc6 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lar appen endre nettleserens logg eller bokmerker lagret på telefonen din. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"stille alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Lar appen stille inn alarmen for en installert alarmklokke-app. Enkelte alarmklokke-apper implementerer kanskje ikke denne funksjonen."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"skrive talepost"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Lar appen endre og fjerne meldinger fra talepostkassen."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"legge til talepost"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lar appen legge til meldinger i talepostkassen din."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"lese talepost"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Lar appen lese taleposten din."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"endre nettleserens tillatelser for geoposisjonering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Lar appen endre nettleserens tillatelser for geoposisjonering. Ondsinnede apper kan bruke dette for å tillate sending av posisjonsinformasjon til vilkårlige nettsteder."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekrefte pakker"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index bff75b5..d5b152d 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1398,10 +1398,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"विश्वस्त प्रतिनिधि सेवालाई बाँध्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"अद्यावधिक र रिकभरी प्रणालीको साथ अन्तर्क्रिया"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"अनुप्रयोगलाई रिकभरी प्रणाली र प्रणाली अद्यावधिकहरूको साथ अन्तर्क्रिया गर्न अनुमति दिन्छ।"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"मिडिया प्रक्षेपण सत्रहरू सिर्जना गर्नुहोस्"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"मिडिया प्रक्षेपण सत्र सिर्जना गर्न अनुप्रयोग लाई अनुमति दिन्छ। यी सत्रले प्रदर्शन र अडियो सामग्री खिच्ने क्षमताका अनुप्रयोगहरू प्रदान गर्न सक्छन्। सामान्य अनुप्रयोगहरूको कहिल्यै पनि आवश्यक पर्दैन।"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"जुम नियन्त्रणको लागि दुई चोटि टच गर्नुहोस्"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट थप गर्न सकिँदैन।"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"जानुहोस्"</string>
@@ -1526,20 +1524,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"सम्पादन गर्नुहोस्"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"डेटा प्रयोग चेतावनी"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"उपयोग र सेटिङहरू हेर्न छुनुहोस्।"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G-3G डेटा बन्द छ"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G डेटा बन्द छ"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"सेलुलर डेटा बन्द छ"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"वाइफाइ डेटा बन्द छ"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"सिमा पुग्यो"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G डेटा सीमा भन्दा पार भएको छ"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G डेटा SIMा नाघ्यो"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"सेलुलर डेटा सीमा नाघ्यो"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"वाइफाइ डेटा SIMा नाघ्यो"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> उल्लेखित सीमा भन्दा बढी छ।"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"पृष्ठभूमिका डेटा प्रतिबन्धित गरिएको छ"</string>
@@ -1760,25 +1752,18 @@
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयन गरियो"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटाइयो"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
-    <skip />
+    <string name="lock_to_app_toast" msgid="2126866321272822564">"तपाईँ अनुप्रयोग बन्द गर्ने ढाँचामा हुनुहुन्छ। निस्कनका लागि हालैको अनुप्रयोगहरूका बटन थिच्नुहोस् र समाउनुहोस्।"</string>
     <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"तपाईं Lock-to-App मोडमा हुनुहुन्छ।"</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"लक-देखि-अनुप्रयोग प्रयोग गर्ने?"</string>
-    <!-- no translation found for lock_to_app_description (2800403592608529611) -->
-    <skip />
-    <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
-    <skip />
+    <string name="lock_to_app_description" msgid="2800403592608529611">"लक-गर्न अनुप्रयोगले एकल अनुप्रयोगमा प्रदर्शन बन्द गर्छ।\n\n,निस्कनका लागि हालैको अनुप्रयोगहरूका बटन थिच्नुहोस् र समाउनुहोस्।"</string>
+    <string name="lock_to_app_negative" msgid="2259143719362732728">"होइन, धन्यवाद"</string>
     <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
-    <!-- no translation found for lock_to_app_start (3074665051586318340) -->
-    <skip />
-    <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
-    <skip />
+    <string name="lock_to_app_start" msgid="3074665051586318340">"अनुप्रयोग बन्द"</string>
+    <string name="lock_to_app_exit" msgid="8967089657201849300">"अनुप्रयोग अब बन्द छैन"</string>
+    <!-- String.format failed for translation -->
     <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
     <skip />
-    <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
-    <skip />
+    <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"शैली बन्द गर्नुहोस"</string>
+    <string name="lock_to_app_unlock_password" msgid="795224196583495868">"पासवर्ड"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 89c18a2..7bcbbe2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op uw telefoon. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"een alarm instellen"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Hiermee kan de app een alarm instellen in een geïnstalleerde wekkerapp. Deze functie wordt door sommige wekkerapps niet geïmplementeerd."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"voicemails schrijven"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Hiermee kan de app berichten in de inbox van uw voicemail aanpassen en verwijderen."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"voicemail toevoegen"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Hiermee kan de app berichten toevoegen aan de inbox van uw voicemail."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"voicemail lezen"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Hiermee kan de app uw voicemails lezen."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"geolocatierechten voor browser aanpassen"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Hiermee kan de app de geolocatierechten van de browser aanpassen. Schadelijke apps kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakketten controleren"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 9da0d6d..3822c4e 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Pozwala aplikacji na modyfikowanie historii i zakładek przeglądarki zapisanych na telefonie. Aplikacja będzie mogła usunąć lub zmodyfikować dane przeglądarki. Uwaga: to uprawnienie może nie być egzekwowane przez przeglądarki innych firm oraz inne aplikacje z możliwością przeglądania internetu."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ustawianie alarmu"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Pozwala aplikacji na ustawienie alarmu w zainstalowanej aplikacji budzika. Funkcja ta może nie być zaimplementowana w niektórych aplikacjach tego typu."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"zapisywanie poczty głosowej"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Zezwala aplikacji na modyfikowanie i usuwanie Twoich odebranych wiadomości poczty głosowej."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodawanie poczty głosowej"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pozwala aplikacji na dodawanie wiadomości do skrzynki odbiorczej poczty głosowej."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"odczytywanie poczty głosowej"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Zezwala aplikacji na odczytywanie poczty głosowej."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modyfikowanie pozwoleń przeglądarki dotyczących lokalizacji geograficznej"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Pozwala aplikacji na modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej. Złośliwe aplikacje mogą używać tej opcji do wysyłania informacji o lokalizacji do dowolnych witryn."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"weryfikowanie pakietów"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6769153..5941e18 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que a aplicação modifique o histórico do Navegador ou marcadores guardados no telemóvel. Isto pode permitir que a aplicação apague ou modifique dados do Navegador. Nota: esta autorização pode não ser aplicada por navegadores de terceiros ou outras aplicações com capacidades de navegação na Web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"definir um alarme"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"escrever mensagens de correio de voz"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Permite que a aplicação modifique e remova mensagens da caixa de entrada de correio de voz."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que a aplicação adicione mensagens à sua caixa de entrada de correio de voz."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"ler correio de voz"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Permite que a aplicação leia as mensagens de correio de voz."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificar permissões de geolocalização do Navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que a aplicação modifique as permissões de geolocalização do navegador. As aplicações maliciosas podem usar isto para permitir o envio de informações de localização para Web sites arbitrárias."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar pacotes"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 024d827..f1a4b96 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite unei aplicații să se asocieze la un serviciu „agent de încredere”."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interacțiune cu sistemul de recuperare și de actualizare"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite unei aplicații să interacționeze cu sistemul de recuperare și cu actualizările de sistem."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Creați sesiuni de proiecție media"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Permite unei aplicații să creeze sesiuni de proiecție media. Aceste sesiuni pot permite aplicațiilor să captureze conținuturi vizuale și audio. Nu trebuie utilizată pentru aplicații obișnuite."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeţi de două ori pentru a mări/micşora"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nu s-a putut adăuga widgetul."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Accesaţi"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editaţi"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertisment de utiliz. a datelor"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Atingeţi pt. a afişa utiliz./set."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Datele 2G-3G sunt dezactivate"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Datele 4G sunt dezactivate"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Datele mobile sunt dezactivate"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Datele Wi-Fi sunt dezactivate"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Limita a fost atinsă"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"S-a depăşit limita de date 2G-3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"S-a depăşit limita de date 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Limită de date mobile depășită"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"S-a depăşit limita de date Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> peste limita specificată."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Datele de fundal restricţionate"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 218c3a54..d74a215 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Приложение сможет подключаться к службе Trust Agents."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаимодействовать с системой восстановления и обновлениями"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Приложение сможет взаимодействовать с системой восстановления и обновлениями системы."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Создание сеансов трансляции контента"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Создание сеансов трансляции контента, во время которых приложение получит доступ к изображению на экране и аудио. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Нажмите дважды для изменения масштаба"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не удалось добавить виджет."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Выбрать"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Изменить"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Осталось мало трафика"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Проверьте трафик и настройки."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Передача данных 2G/3G отключена"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Передача данных 4G отключена"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Передача мобильных данных отключена"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Передача данных Wi-Fi отключена"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Достигнут лимит"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Превышен лимита трафика 2G и 3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Превышен лимит на трафик 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Превышен лимит мобильного трафика"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Превышен лимит трафика Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Лимит превышен на <xliff:g id="SIZE">%s</xliff:g>."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Фоновый режим ограничен"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 331db28..38b153d 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1755,25 +1755,16 @@
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> තෝරාගෙන ඇත"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> මකා දමන ලදි"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
-    <skip />
+    <string name="lock_to_app_toast" msgid="2126866321272822564">"යෙදුමට-අඟුළු දැමීමේ ආකාරය තුළ ඔබ සිටි. පිටවීමට, මෑත යෙදුම් බොත්තම ඔබා අල්ලා ගෙන සිටින්න"</string>
     <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"යෙදුමට-අඟුළු දැමීමේ ආකාරය තුළ ඔබ සිටි."</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"අගුළු-යෙදුම භාවිතා කරන්නද?"</string>
-    <!-- no translation found for lock_to_app_description (2800403592608529611) -->
-    <skip />
-    <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
-    <skip />
+    <string name="lock_to_app_description" msgid="2800403592608529611">"අගුළු-යෙදුම තනි යෙදුමක පෙනුම අගුළු දමයි.\n\nඉවත්ව යාමට මෑත යෙදුම් බොත්තම ඔබා රඳවා ගන්න"</string>
+    <string name="lock_to_app_negative" msgid="2259143719362732728">"නැත, ස්තූතියි"</string>
     <string name="lock_to_app_positive" msgid="7085139175671313864">"ආරම්භය"</string>
-    <!-- no translation found for lock_to_app_start (3074665051586318340) -->
-    <skip />
-    <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
-    <skip />
-    <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
-    <skip />
+    <string name="lock_to_app_start" msgid="3074665051586318340">"යෙදුමට-අඟුළු දැමීම"</string>
+    <string name="lock_to_app_exit" msgid="8967089657201849300">"යෙදුමට අඟුළු දැමීම තවදුරටත් නැත"</string>
+    <string name="lock_to_app_use_screen_lock" msgid="1434584309048590886">"පිටවීමට පෙර %1$s සඳහා ආසන්න"</string>
+    <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"අඟුළු ඇරීමේ රටාව"</string>
+    <string name="lock_to_app_unlock_password" msgid="795224196583495868">"මුරපදය"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 00f22bb..63bb72b 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikácii viazať sa na službu zástupcu dôveryhodnosti."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcia so systémom aktualizácií a obnovenia"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Umožňuje aplikácii interakciu so systémom obnovenia a s aktualizáciami systému."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Vytváranie relácií projekcie médií"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Umožňuje aplikácii vytvárať relácie projekcie médií. Tieto relácie môžu aplikáciám umožniť zaznamenávať obsah na obrazovke a zvukový obsah. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Ovládacie prvky lupy zobrazíte dvojitým dotknutím"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Miniaplikáciu sa nepodarilo pridať."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Hľadať"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Upraviť"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozornenie o využití dát"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Zobr. využív. dát a nastavení."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"dáta 2G–3G sú vypnuté"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"dáta 4G sú vypnuté"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Mobilné dáta sú vypnuté"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Dáta siete Wi-Fi sú vypnuté"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Dosiahli ste limit"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G, 3G dátový limit prekročený"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Dátový limit 4G bol prekročený"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Presiahli ste limit mobil. dát"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Dát. limit Wi-Fi bol prekročený"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> nad stanovenou hranicou."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Údaje na pozadí sú obmedzené"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index bfc28ca..cda7606 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1186,9 +1186,9 @@
     <string name="whichApplicationNamed" msgid="8260158865936942783">"Dokončanje dejanja z aplikacijo %1$s"</string>
     <string name="whichViewApplication" msgid="3272778576700572102">"Odpiranje z aplikacijo"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Odpiranje z aplikacijo %1$s"</string>
-    <string name="whichEditApplication" msgid="144727838241402655">"Urejanje z"</string>
+    <string name="whichEditApplication" msgid="144727838241402655">"Urejanje z aplikacijo"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Urejanje z aplikacijo %1$s"</string>
-    <string name="whichSendApplication" msgid="6902512414057341668">"Skupna raba z"</string>
+    <string name="whichSendApplication" msgid="6902512414057341668">"Skupna raba z aplikacijo"</string>
     <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Skupna raba z aplikacijo %1$s"</string>
     <string name="whichHomeApplication" msgid="4616420172727326782">"Izberite aplikacijo za začetno stran"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Privzeta uporaba za to dejanje."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 25e3c8d..c234818 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Дозвољава апликацији да мења историју Прегледача или обележиваче ускладиштене на телефону. Ово може да омогући апликацији да брише или мења податке Прегледача. Напомена: Ова дозвола се можда на примењује на прегледаче треће стране и друге апликације са могућношћу веб прегледања."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"подешавање аларма"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Дозвољава апликацији да подеси аларм у инсталираној апликацији будилника. Неке апликације будилника можда не примењују ову функцију."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"пиши поруке говорне поште"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Дозвољава апликацији да мења и уклања поруке из пријемног сандучета говорне поште."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"додавање говорне поште"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозвољава апликацији да додаје поруке у пријемно сандуче говорне поште."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"читај говорну пошту"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Дозвољава апликацији да чита поруке говорне поште."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"измена дозвола за географске локације Прегледача"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Дозвољава апликацији да измени дозволе Прегледача за утврђивање географске локације. Злонамерне апликације то могу да злоупотребе и искористе за слање информација о локацији насумичним веб сајтовима."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"верификовање пакета"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозвољава апликацији да се веже за услугу Trust agents."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Интеракција са системом за ажурирање и опоравак"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Дозвољава апликацији да ступа у интеракцију са системом за опоравак и ажурирањима система."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Прави сесије пројекција медија"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Омогућава апликацији да прави сесије пројекција медија. Ове сесије могу да омогуће апликацијама да снимају садржај на екрану или аудио садржај. Никада не би требало да буде потребно за стандардне апликације."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Додирните двапут да бисте контролисали зум"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Није могуће додати виџет."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Иди"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Измени"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Упозорење о потрошњи података"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Додирните за преглед кор. и под."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G–3G подаци су искључени"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G подаци су искључени"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Мобилни подаци су искључени"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi подаци су искључени"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Ограничење је достигнуто"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Прекорачен пренос 2G-3G података"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Прекорачење преноса 4G података"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Ограничење мобилних података је прекорачено"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Прекорачење преноса Wi-Fi подат."</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> преко наведеног ограничења."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Позадински подаци су ограничени"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 6b885d9..913bc90 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Tillåter att appen ändrar historiken för besökta sidor i webbläsaren eller bokmärken som sparats på telefonen. Det kan innebära att appen kan ta bort eller ändra webbläsarinformation. Observera att den här behörigheten kanske inte är tillämplig för webbläsare från tredje part eller andra appar med surffunktion."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ställa in ett alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Tillåter att appen ställer in ett alarm i en befintlig alarmapp. Vissa alarmappar har inte den här funktionen."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"skriva röstmeddelanden"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Tillåter att appen ändrar och tar bort meddelanden från röstbrevlådans inkorg."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"lägg till röstbrevlåda"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Gör att appen lägger till meddelanden i röstbrevlådans inkorg."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"läsa röstmeddelanden"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Tillåter att appen läser dina röstmeddelanden."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Ändra geografisk plats för webbläsaren"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillåter att appen ändrar webbläsarens behörigheter för geografisk plats. Skadliga appar kan använda detta för att tillåta att platsinformation skickas till godtyckliga webbplatser."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"kontrollera paket"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a9c3c52..acbef24 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -719,8 +719,8 @@
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bandika kwenye huduma ya mtoa masharti"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kubandika kwenye kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Isihitajike kamwe kwa pogramu za kawaida."</string>
-    <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"shurutisha kwa huduma ya njia za sauti, picha na video."</string>
-    <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Humruhusu mmiliki kushurutisha kwa kiolesura cha ngazi ya juu cha huduma ya njia za sauti, picha na video. Haipaswi kuhitajika kwa programu za kawaida."</string>
+    <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"bandika kwenye huduma ya njia za sauti, picha na video."</string>
+    <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Humruhusu mmiliki kubandika kwenye kiolesura cha ngazi ya juu cha huduma ya njia za sauti, picha na video. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"shurutisha kwa huduma murua"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"Huruhusu mmiliki kushurutisha kwenye kiolesura cha kiwango cha juu cha huduma murua. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"omba programu ya usakinishaji inayotolewa na mtoa huduma."</string>
@@ -1292,10 +1292,10 @@
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Ruhusu Kila mara"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Usiruhusu Kamwe"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM kadi imeondolewa"</string>
-    <string name="sim_removed_message" msgid="5450336489923274918">"Mtandao wa simu za mkononi hautapatikana hadi utakapoanzisha tena kifaa chako kikiwa kimeingizwa SIM kadi sahihi."</string>
+    <string name="sim_removed_message" msgid="5450336489923274918">"Mitandao ya simu za mkononi haitapatikana hadi utakapozima na kuwasha tena kifaa chako kikiwa kimeingizwa SIM kadi sahihi."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Nimemaliza"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kadi imeongezwa"</string>
-    <string name="sim_added_message" msgid="7797975656153714319">"Anzisha kifaa chako tena ili ufikie mitandao ya simu za mkononi."</string>
+    <string name="sim_added_message" msgid="7797975656153714319">"Zima na uwashe kifaa chako tena ili ufikie mitandao ya simu za mkononi."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Anza upya"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index e74feb4..eacc824 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"உங்கள் மொபைலில் சேமிக்கப்பட்ட உலாவியின் வரலாறு அல்லது புத்தகக்குறிகளைத் திருத்த பயன்பாட்டை அனுமதிக்கிறது. இது உலாவியின் தரவை அழிக்கவோ, திருத்தவோ பயன்பாட்டை அனுமதிக்கலாம். குறிப்பு: இணைய உலாவல் செயல்திறன்கள் மூலம் மூன்றாம் தரப்பு உலாவிகள் அல்லது பிற பயன்பாடுகள் இந்த அனுமதியைச் செயற்படுத்த முடியாது."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"அலாரத்தை அமைத்தல்"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"நிறுவிய அலார கடிகாரப் பயன்பாட்டில் அலாரத்தை அமைக்க, பயன்பாட்டை அனுமதிக்கிறது. சில அலார கடிகார பயன்பாடுகளில் இந்த அம்சம் இல்லாமல் இருக்கலாம்."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"குரலஞ்சல்களை எழுது"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"குரலஞ்சல் இன்பாக்ஸிலிருந்து செய்திகளைத் திருத்தவும் அகற்றவும், பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"குரலஞ்சலைச் சேர்த்தல்"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"குரலஞ்சல் இன்பாக்ஸில் செய்திகளைச் சேர்க்க, பயன்பாட்டை அனுமதிக்கிறது."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"குரலஞ்சலைப் படி"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"குரலஞ்சல்களைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"உலாவியின் புவியியல் இருப்பிடம் சார்ந்த அனுமதிகளைத் திருத்துதல்"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"உலாவியின் புவியியல் இருப்பிடம் சார்ந்த அனுமதிகளைத் திருத்த, பயன்பாட்டை அனுமதிக்கிறது. இடத் தகவலை தன்னிச்சையான இணையதளங்களுக்கு அனுப்புவதை அனுமதிக்க, தீங்குவிளைவிக்கும் பயன்பாடுகள் இதைப் பயன்படுத்தலாம்."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"தொகுப்புகளைச் சரிபார்த்தல்"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index f951d5c..b373cc7 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"మీ ఫోన్‌లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్‌మార్క్‌లను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి అనువర్తనాన్ని అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్‌లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర అనువర్తనాల ద్వారా అమలు చేయబడకపోవచ్చు."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"అలారం సెట్ చేయడం"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ఇన్‌స్టాల్ చేయబడిన అలారం గడియారం అనువర్తనంలో అలారంను సెట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. కొన్ని అలారం గల గడియారం అనువర్తనాలు ఈ లక్షణాన్ని అమలు చేయకపోవచ్చు."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"వాయిస్ మెయిల్‌లను వ్రాయడం"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"మీ వాయిస్ మెయిల్ ఇన్‌బాక్స్ నుండి సందేశాలను సవరించడానికి మరియు తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"వాయిస్ మెయిల్‌ను జోడించడం"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"మీ వాయిస్ మెయిల్ ఇన్‌బాక్స్‌కి సందేశాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"వాయిస్ మెయిల్‌లను చదవడం"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"మీ వాయిస్ మెయిల్‌లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"బ్రౌజర్ భౌగోళిక స్థానం అనుమతులను సవరించడం"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"బ్రౌజర్ యొక్క భౌగోళిక స్థానం అనుమతులను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు ఏకపక్ష వెబ్ సైట్‌లకు స్థాన సమాచారాన్ని అనుమతించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ప్యాకేజీలను ధృవీకరించడం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d546738..31ad764 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในโทรศัพท์ ซึ่งทำให้แอปพลิเคชันสามารถลบหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ตั้งปลุก"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"อนุญาตให้แอปพลิเคชันตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้ง แอปพลิเคชันนาฬิกาปลุกบางรายการอาจไม่ใช้คุณลักษณะนี้"</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"เขียนข้อความเสียง"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"อนุญาตให้แอปแก้ไขและนำข้อความออกจากกล่องข้อความเสียงของคุณ"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"เพิ่มข้อวามเสียง"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"อนุญาตให้แอปพลิเคชันเพิ่มข้อความลงในกล่องข้อความเสียงของคุณ"</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"อ่านข้อความเสียง"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"อนุญาตให้แอปอ่านข้อความเสียงของคุณได้"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"อนุญาตให้แอปพลิเคชันแก้ไขการอนุญาตตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์ แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการส่งข้อมูลตำแหน่งไปยังเว็บไซต์ต่างๆ ได้ตามต้องการ"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ยืนยันแพ็กเกจ"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"อนุญาตให้แอปพลิเคชันผูกกับบริการของตัวแทนที่เชื่อถือได้"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"โต้ตอบกับการอัปเดตและระบบการกู้คืน"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ช่วยให้แอปพลิเคชันสามารถโต้ตอบกับระบบการกู้คืนและการอัปเดตระบบ"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"สร้างเซสชันการฉายภาพสื่อ"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"อนุญาตให้แอปพลิเคชันสร้างเซสชันการฉายภาพสื่อ เซสชันดังกล่าวช่วยให้แอปพลิเคชันสามารถจับภาพหน้าจอและเนื้อหาเสียงได้ แอปทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"แตะสองครั้งเพื่อควบคุมการซูม"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ไม่สามารถเพิ่มวิดเจ็ต"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"ไป"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"แก้ไข"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"คำเตือนการใช้ข้อมูล"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"แตะเพื่อดูการใช้งานและการตั้งค่า"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"ข้อมูล 2G-3G ปิดอยู่"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"ข้อมูล 4G ปิดอยู่"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"ข้อมูลมือถือปิดอยู่"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"ข้อมูล Wi-Fi ปิดอยู่"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"ถึงขีดจำกัดแล้ว"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"เกินขีดจำกัดข้อมูล 2G - 3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"เกินขีดจำกัดของข้อมูล 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"ถึงขีดจำกัดข้อมูลมือถือแล้ว"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"เกินขีดจำกัดข้อมูล WiFi แล้ว"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> เกินขีดจำกัดที่ระบุไว้"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"จำกัดข้อมูลแบ็กกราวด์"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 377708c..36990ee 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -719,10 +719,8 @@
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nagbibigay-daan sa may-ari na mapailalim sa interface sa tuktok na antas ng isang serbisyo ng notification listener. Hindi dapat kailanganin para sa karaniwang apps kahit kailan."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"i-bind sa isang serbisyo sa pagbibigay ng kundisyon"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Nagbibigay-daan sa naghahawak na i-bind ang top-level na interface ng isang serbisyo sa pagbibigay ng kundisyon. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
-    <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
-    <skip />
-    <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
-    <skip />
+    <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"mag-bind sa isang serbisyo ng media route"</string>
+    <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Nagbibigay-daan sa may-hawak na mag-bind sa top-level na interface ng isang serbisyo ng media route. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"sumailalim sa isang serbisyo ng dream"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"Pinapayagan ang may-ari na sumailalim sa interface ng serbisyo ng dream na nasa nangungunang antas. Hindi kailanman dapat na kailanganin para sa mga normal na app."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"paganahin ang app ng configuration na ibinigay ng carrier"</string>
@@ -1008,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Pinapayagan ang app na baguhin ang kasaysayan o mga bookmark ng Browser na naka-imbak sa iyong telepono. Maaari nitong payagan ang app na burahin o baguhin ang data ng Browser. Tandaan: hindi maaaring ipatupad ang pahintulot na ito ng mga third-party na browser o iba pang mga application na may mga kakayahan sa pagba-browse sa web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"magtakda ng alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Pinapayagan ang app na magtakda ng alarm sa isang naka-install na app ng alarm clock. Maaaring hindi ipatupad ng ilang apps ng alarm clock ang tampok na ito."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"sumulat ng mga voicemail"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Pinapayagan ang app na magbago at mag-alis ng mga mensahe sa iyong inbox ng voicemail."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"magdagdag ng voicemail"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pinapayagan ang app na magdagdag ng mga mensahe sa iyong inbox ng voicemail."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"basahin ang voicemail"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Pinapayagan ang app na basahin ang iyong mga voicemail."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"baguhin ang mga pahintulot ng geolocation ng Browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Pinapayagan ang app na baguhin ang mga pahintulot sa geolocation ng Browser. Maaari itong gamitin ng nakakahamak na apps upang payagan ang pagpapadala ng impormasyon ng lokasyon sa mga hindi tukoy na web site."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"i-verify ang mga package"</string>
@@ -1185,20 +1179,13 @@
     <string name="capital_on" msgid="1544682755514494298">"I-ON"</string>
     <string name="capital_off" msgid="6815870386972805832">"I-OFF"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Kumpletuhin ang pagkilos gamit ang"</string>
-    <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
-    <skip />
-    <!-- no translation found for whichViewApplication (3272778576700572102) -->
-    <skip />
-    <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
-    <skip />
-    <!-- no translation found for whichEditApplication (144727838241402655) -->
-    <skip />
-    <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
-    <skip />
-    <!-- no translation found for whichSendApplication (6902512414057341668) -->
-    <skip />
-    <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
-    <skip />
+    <string name="whichApplicationNamed" msgid="8260158865936942783">"Tapusin ang pagkilos gamit ang %1$s"</string>
+    <string name="whichViewApplication" msgid="3272778576700572102">"Buksan gamit ang"</string>
+    <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Buksan gamit ang %1$s"</string>
+    <string name="whichEditApplication" msgid="144727838241402655">"I-edit gamit ang"</string>
+    <string name="whichEditApplicationNamed" msgid="1775815530156447790">"I-edit gamit ang %1$s"</string>
+    <string name="whichSendApplication" msgid="6902512414057341668">"Ibahagi gamit ang"</string>
+    <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Ibahagi gamit ang %1$s"</string>
     <string name="whichHomeApplication" msgid="4616420172727326782">"Pumili ng home app"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Gamitin bilang default para sa pagkilos na ito."</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"I-clear ang default sa mga setting ng System &gt; Apps &gt; Na-download."</string>
@@ -1301,12 +1288,10 @@
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Palaging Payagan"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Huwag kailanman Payagan"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"Naalis ang SIM card"</string>
-    <!-- no translation found for sim_removed_message (5450336489923274918) -->
-    <skip />
+    <string name="sim_removed_message" msgid="5450336489923274918">"Magiging unavailable ang cellular network hanggang mag-restart ka nang may nakalagay na wastong SIM card."</string>
     <string name="sim_done_button" msgid="827949989369963775">"Tapos na"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"Idinagdag ang SIM card"</string>
-    <!-- no translation found for sim_added_message (7797975656153714319) -->
-    <skip />
+    <string name="sim_added_message" msgid="7797975656153714319">"I-restart ang iyong device upang ma-access ang cellular network."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"I-restart"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Magtakda ng oras"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Itakda ang petsa"</string>
@@ -1401,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Pinapayagan ang isang application na sumailalim sa isang serbisyo ng trust agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Makipag-ugnay sa system ng pag-update at pagbawi"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Binibigyang-daan ang isang application na makipag-ugnay sa system ng pagbawi at mga pag-update ng system."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Gumawa ng mga media projection session"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Nagbibigay-daan sa isang application upang gumawa ng mga media projection session. Makakapagbigay ang mga session na ito ng kakayahan sa mga application na ma-capture ang mga nilalaman ng display at audio. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Pindutin nang dalawang beses para sa pagkontrol ng zoom"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Hindi maidagdag ang widget."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Pumunta"</string>
@@ -1529,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"I-edit"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Babala sa paggamit ng data"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Pindutin upang tingnan ang paggamit at mga setting."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Naka-off ang 2G-3G data"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Naka-off ang 4G data"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Naka-off ang cellular data"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Naka-off ang Wi-Fi data"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Naabot na ang limitasyon"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"lumampas sa 2G-3G na limitasyon ng data"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Lumampas sa 4G na limitasyon ng data"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Lampas na sa cellular data limit"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Lumampas sa limitasyon ng data ng Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Lampas ng <xliff:g id="SIZE">%s</xliff:g> sa tinukoy na limitasyon."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Pinaghihigpitan ang data ng background"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 7433771..3f79c61 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Bir uygulamanın, güven aracı hizmetine bağlanmasına izin verir."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Güncelleme ve kurtarma sistemiyle etkileşim kur"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Bir uygulamaya, kurtarma sistemi ve sistem güncellemeriyle etkileşim kurma izni verir."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Medya yansıtma oturumları oluştur"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Bir uygulamanın medya yansıtma oturumları oluşturmasına izin verir. Bu oturumlar, uygulamaların görüntü ve ses içeriklerini kaydetmesine olanak sağlar. Normal uygulamalar için hiçbir zaman gerekli olmaz."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Yakınlaştırma denetimi için iki kez dokunun"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget eklenemedi."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Git"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Düzenle"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Veri kullanım uyarısı"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Kullanımı ve ayarları görmek için dokunun."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G-3G veri kullanımı kapalı"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G veri kullanımı kapalı"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Hücresel veri kapalı"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Kablosuz veri kapalı"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Sınıra ulaşıldı"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G veri limiti aşıldı"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G veri limiti aşıldı"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Hücresel veri sınırı aşıldı"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Kablosuz veri limiti aşıldı"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g>, belirlenen limiti aşıyor."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Arka plan verileri kısıtlı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index eeb6e15..ac415eb 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Дозволяє програмі змінювати історію чи закладки веб-переглядача, збережені у вашому телефоні. Це може дозволити програмі стирати чи змінювати дані веб-переглядача. Зауважте: цей дозвіл не може застосовуватися веб-переглядачами третіх сторін або іншими програмами з можливостями веб-перегляду."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"установлювати будильник"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Дозволяє програмі налаштовувати сигнал у встановленій програмі будильника. У деяких програмах будильника ця функція може не застосовуватися."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"записувати голосові повідомлення"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Додаток може змінювати голосові повідомлення та видаляти їх із папки \"Вхідні\"."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"додавати голосову пошту"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозволяє програмі додавати повідомлення в папку \"Вхідні\" голосової пошти."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"читати голосові повідомлення"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Додаток може читати голосові повідомлення."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"змінювати дозволи географічного місцезнаходження у веб-переглядачі"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Дозволяє програмі змінювати дозволи географічного місцезнаходження у веб-переглядачі. Шкідливі програми можуть використовувати це, щоб дозволяти надсилати інформацію про місцезнаходження довільним веб-сайтам."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"перевіряти пакети"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозволяє додатку прив’язуватися до служби довірчих агентів."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаємодіяти з оновленнями системи та системою відновлення."</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Дозволяє додатку взаємодіяти із системою відновлення й оновленнями системи."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Створювати сеанси проектування медіа"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Додаток може створювати сеанси проектування медіа. Під час цих сеансів додатки зможуть збирати аудіовміст і вміст дисплея. Не використовується звичайними додатками."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Двічі торкніться, щоб керувати масштабом"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не вдалося додати віджет."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Йти"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Редагувати"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Застереження про використ. даних"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Торкн.,щоб див. викор. і налашт."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Дані 2G–3G вимкнено"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Дані 4G вимкнено"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Мобільні дані вимкнено"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Дані Wi-Fi вимкнено"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Досягнуто ліміту"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Перевищено ліміт даних 2G–3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Перевищено ліміт даних 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Перевищено ліміт мобільних даних"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Перевищено ліміт даних Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> – понад указаний ліміт."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Викор-ня фонових даних обмежено"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 7da441c..c3feb4c 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -720,7 +720,7 @@
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"شرط فراہم کرنے والی ایک سروس کے پابند بنیں"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"حامل کو شرط فراہم کنندہ کی سروس کے اعلی سطحی انٹرفیس کا پابند ہونے کی اجازت دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہيں ہونی چاہئے۔"</string>
     <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"میڈیا روٹ سروس کا پابند بنیں"</string>
-    <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"حامل کو میڈیا روٹ سروس کے اعلی سطحی انٹرفیس کا پابند کرنے کی اجازت دیتا ہے۔ معمول کے ایپس کیلئے کبھی درکار نہیں ہونا چاہئے۔"</string>
+    <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"حامل کو میڈیا روٹ سروس کے اعلی سطحی انٹرفیس کا پابند کرنے کی اجازت دیتا ہے۔ معمول کی ایپس کیلئے کبھی درکار نہیں ہونا چاہئے۔"</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"ایک ڈریم سروس کا پابند بنیں"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"حامل کو ڈریم سروس کے اعلی سطحی انٹرفیس کا پابند ہونے کی اجازت دیتی ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہيں ہونی چاہیے۔"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"کیریئر کے ذریعے فراہم کردہ کنفگریشن ایپ طلب کریں"</string>
@@ -1292,10 +1292,10 @@
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ہمیشہ اجازت دیں"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"کبھی بھی اجازت نہ دیں"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"‏SIM کارڈ ہٹا دیا گیا"</string>
-    <string name="sim_removed_message" msgid="5450336489923274918">"‏سیلولر نیٹ ورک اس وقت تک دستیاب نہیں ہو گا جب تک آپ ایک درست SIM داخل کرکے اسے دوبارہ چالو نہ کریں۔"</string>
+    <string name="sim_removed_message" msgid="5450336489923274918">"‏سیلولر نیٹ ورک اس وقت تک دستیاب نہیں ہو گا جب تک آپ ایک درست SIM داخل کرکے اسے دوبارہ سٹارٹ نہ کریں۔"</string>
     <string name="sim_done_button" msgid="827949989369963775">"ہو گیا"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"‏SIM شامل کیا گیا"</string>
-    <string name="sim_added_message" msgid="7797975656153714319">"سیلولر نیٹ ورک تک رسائی کیلئے اپنا آلہ دوبارہ چالو کریں۔"</string>
+    <string name="sim_added_message" msgid="7797975656153714319">"سیلولر نیٹ ورک تک رسائی کیلئے اپنا آلہ دوبارہ سٹارٹ کریں۔"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"دوبارہ شروع کریں"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"وقت سیٹ کریں"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ سیٹ کریں"</string>
@@ -1390,10 +1390,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"ایک ایپلیکیشن کو ایک ٹرسٹ ایجنٹ سروس کا پابند ہونے دیتا ہے۔"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"اپ ڈیٹ اور بازیابی سسٹم کے ساتھ تعامل کریں"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"کسی ایپ کو بازیابی سسٹم اور بازیابی اپ ڈیٹس کے ساتھ تعامل کرنے کی اجازت دیتا ہے۔"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"میڈیا پروجیکشن سیشنز بنائیں"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"ایک ایپلیکیشن کو میڈیا پروجیکشن سیشنز بنانے کی اجازت دیتی ہے۔ یہ سیشنز ایپلیکیشنز کو ڈسپلے اور آڈیو مواد کو کیپچر کرنے کی اہلیت فراہم کر سکتے ہیں۔ عام ایپس کو کبھی بھی ان کی ضرورت نہیں ہونی چاہیے۔"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"زوم کے کنٹرول کیلئے دو بار ٹچ کریں"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ویجٹس کو شامل نہیں کرسکا۔"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"جائیں"</string>
@@ -1518,20 +1516,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"ترمیم کریں"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"ڈیٹا کے استعمال کی وارننگ"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"استعمال و ترتیبات دیکھنے کیلئے ٹچ کریں۔"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"‏2G-3G ڈیٹا آف ہے"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"‏4G ڈیٹا آف ہے"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"سیلولر ڈیٹا آف ہے"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"‏Wi-Fi ڈیٹا آف ہے"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"حد تک پہنچ گیا"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"‏2G-3G ڈیٹا حد سے متجاوز ہو گیا"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"‏4G ڈیٹا حد سے متجاوز ہو گیا"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"سیلولر ڈیٹا کی حد سے تجاوز کرگیا"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"‏Wi-Fi ڈیٹا حد سے متجاوز ہو گیا"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> متعینہ حد سے زیادہ ہے۔"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"پس منظر ڈیٹا محدود ہے"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7ef5017..b1c7acc 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên điện thoại của bạn. Việc này có thể cho phép ứng dụng xóa hoặc sửa đổi dữ liệu của Trình duyệt. Lưu ý: quyền này có thể không được thực thi bởi các trình duyệt của bên thứ ba hoặc các ứng dụng khác có khả năng duyệt web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"đặt báo thức"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không thực thi tính  năng này."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"viết thư thoại"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Cho phép ứng dụng sửa đổi và xóa thư khỏi hộp thư thoại đến của bạn."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"thêm thư thoại"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Cho phép ứng dụng thêm thông báo vào hộp thư thoại đến của bạn."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"đọc thư thoại"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Cho phép ứng dụng đọc thư thoại của bạn."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"sửa đổi các quyền về vị trí địa lý của Trình duyệt"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Cho phép ứng dụng sửa đổi cấp phép vị trí địa lý của Trình duyệt. Ứng dụng độc hại có thể lợi dụng quyền này để cho phép gửi thông tin vị trí tới các trang web tùy ý."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"xác minh gói"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Cho phép ứng dụng liên kết với một dịch vụ của đại lý đáng tin cậy."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Tương tác với hệ thống khôi phục và bản cập nhật"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Cho phép ứng dụng tương tác với hệ thống khôi phục và bản cập nhật hệ thống."</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"Tạo phiên chiếu phương tiện"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"Cho phép ứng dụng tạo các phiên chiếu phương tiện. Các phiên này có thể cấp cho ứng dụng khả năng chụp màn hình và ghi nội dung âm thanh. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Chạm hai lần để kiểm soát thu phóng"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Không thể thêm tiện ích."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Đến"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Chỉnh sửa"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Cảnh báo sử dụng dữ liệu"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"Chạm để xem sử dụng và cài đặt."</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"Dữ liệu 2G-3G bị tắt"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"Dữ liệu 4G bị tắt"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"Dữ liệu di động bị tắt"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Dữ liệu Wi-Fi bị tắt"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"Đã đạt giới hạn"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Đã vượt quá g.hạn dữ liệu 2G-3G"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Đã vượt quá giới hạn dữ liệu 4G"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Đã vượt quá giới hạn dữ liệu DĐ"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Vượt quá g.hạn d.liệu Wi-Fi"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> vượt quá g.hạn được chỉ định."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Dữ liệu nền bị giới hạn"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ac91926..be51b82 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -120,7 +120,7 @@
     <string name="roamingTextSearching" msgid="8360141885972279963">"正在搜索服务"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
-    <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g> 秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
+    <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g>秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
     <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
     <string name="fcComplete" msgid="3118848230966886575">"功能代码已拨完。"</string>
@@ -188,7 +188,7 @@
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即锁定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
-    <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
+    <string name="android_system_label" msgid="6577375335728551336">"Android系统"</string>
     <string name="user_owner_label" msgid="6465364741001216388">"个人应用"</string>
     <string name="managed_profile_label" msgid="6260850669674791528">"工作"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
@@ -643,8 +643,8 @@
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"允许应用更改网络连接的状态。"</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"更改网络共享连接"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"允许应用更改绑定网络连接的状态。"</string>
-    <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"更改后台数据使用设置"</string>
-    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允许应用更改后台数据使用设置。"</string>
+    <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"更改后台流量设置"</string>
+    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允许应用更改后台流量设置。"</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"查看 WLAN 连接"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"允许该应用查看 WLAN 网络的相关信息,例如是否启用了 WLAN 以及连接的 WLAN 设备的名称。"</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"连接 WLAN 和断开连接"</string>
@@ -921,7 +921,7 @@
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地尝试解锁手机。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,手机将重置为出厂默认设置,所有用户数据将会丢失。"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁平板电脑。平板电脑现在将重置为出厂默认设置。"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁手机。手机现在将重置为出厂默认设置。"</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g>秒后重试。"</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"忘记了图案?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"帐户解锁"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"图案尝试次数过多"</string>
@@ -1051,69 +1051,69 @@
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"1 个月前"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 个月前"</string>
   <plurals name="num_seconds_ago">
-    <item quantity="one" msgid="4869870056547896011">"1 秒前"</item>
-    <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
+    <item quantity="one" msgid="4869870056547896011">"1秒前"</item>
+    <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g>秒前"</item>
   </plurals>
   <plurals name="num_minutes_ago">
-    <item quantity="one" msgid="3306787433088810191">"1 分钟前"</item>
-    <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分钟前"</item>
+    <item quantity="one" msgid="3306787433088810191">"1分钟前"</item>
+    <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g>分钟前"</item>
   </plurals>
   <plurals name="num_hours_ago">
-    <item quantity="one" msgid="9150797944610821849">"1 小时前"</item>
-    <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小时前"</item>
+    <item quantity="one" msgid="9150797944610821849">"1小时前"</item>
+    <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>小时前"</item>
   </plurals>
   <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"过去 <xliff:g id="COUNT">%d</xliff:g> 天"</item>
+    <item quantity="other" msgid="3069992808164318268">"过去<xliff:g id="COUNT">%d</xliff:g>天"</item>
   </plurals>
-    <string name="last_month" msgid="3959346739979055432">"上月"</string>
+    <string name="last_month" msgid="3959346739979055432">"上个月"</string>
     <string name="older" msgid="5211975022815554840">"往前"</string>
   <plurals name="num_days_ago">
     <item quantity="one" msgid="861358534398115820">"昨天"</item>
-    <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
+    <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g>天前"</item>
   </plurals>
   <plurals name="in_num_seconds">
-    <item quantity="one" msgid="2729745560954905102">"1 秒后"</item>
-    <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> 秒后"</item>
+    <item quantity="one" msgid="2729745560954905102">"1秒后"</item>
+    <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g>秒后"</item>
   </plurals>
   <plurals name="in_num_minutes">
-    <item quantity="one" msgid="8793095251325200395">"1 分钟后"</item>
-    <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> 分钟后"</item>
+    <item quantity="one" msgid="8793095251325200395">"1分钟后"</item>
+    <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g>分钟后"</item>
   </plurals>
   <plurals name="in_num_hours">
-    <item quantity="one" msgid="7164353342477769999">"1 小时后"</item>
-    <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> 小时后"</item>
+    <item quantity="one" msgid="7164353342477769999">"1小时后"</item>
+    <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g>小时后"</item>
   </plurals>
   <plurals name="in_num_days">
     <item quantity="one" msgid="5413088743009839518">"明天"</item>
     <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> 天后"</item>
   </plurals>
   <plurals name="abbrev_num_seconds_ago">
-    <item quantity="one" msgid="1849036840200069118">"1 秒前"</item>
-    <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
+    <item quantity="one" msgid="1849036840200069118">"1秒前"</item>
+    <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g>秒前"</item>
   </plurals>
   <plurals name="abbrev_num_minutes_ago">
-    <item quantity="one" msgid="6361490147113871545">"1 分钟前"</item>
-    <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> 分钟前"</item>
+    <item quantity="one" msgid="6361490147113871545">"1分钟前"</item>
+    <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g>分钟前"</item>
   </plurals>
   <plurals name="abbrev_num_hours_ago">
-    <item quantity="one" msgid="4796212039724722116">"1 小时前"</item>
-    <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小时前"</item>
+    <item quantity="one" msgid="4796212039724722116">"1小时前"</item>
+    <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g>小时前"</item>
   </plurals>
   <plurals name="abbrev_num_days_ago">
     <item quantity="one" msgid="8463161711492680309">"昨天"</item>
-    <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
+    <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g>天前"</item>
   </plurals>
   <plurals name="abbrev_in_num_seconds">
-    <item quantity="one" msgid="5842225370795066299">"1 秒后"</item>
-    <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> 秒后"</item>
+    <item quantity="one" msgid="5842225370795066299">"1秒后"</item>
+    <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g>秒后"</item>
   </plurals>
   <plurals name="abbrev_in_num_minutes">
-    <item quantity="one" msgid="562786149928284878">"1 分钟后"</item>
-    <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> 分钟后"</item>
+    <item quantity="one" msgid="562786149928284878">"1分钟后"</item>
+    <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g>分钟后"</item>
   </plurals>
   <plurals name="abbrev_in_num_hours">
-    <item quantity="one" msgid="3274708118124045246">"1 小时后"</item>
-    <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> 小时后"</item>
+    <item quantity="one" msgid="3274708118124045246">"1小时后"</item>
+    <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g>小时后"</item>
   </plurals>
   <plurals name="abbrev_in_num_days">
     <item quantity="one" msgid="2178576254385739855">"明天"</item>
@@ -1135,16 +1135,16 @@
     <string name="year" msgid="4001118221013892076">"年"</string>
     <string name="years" msgid="6881577717993213522">"年"</string>
   <plurals name="duration_seconds">
-    <item quantity="one" msgid="6962015528372969481">"1 秒"</item>
-    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> 秒"</item>
+    <item quantity="one" msgid="6962015528372969481">"1秒"</item>
+    <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>秒"</item>
   </plurals>
   <plurals name="duration_minutes">
-    <item quantity="one" msgid="4915414002546085617">"1 分钟"</item>
-    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> 分钟"</item>
+    <item quantity="one" msgid="4915414002546085617">"1分钟"</item>
+    <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>分钟"</item>
   </plurals>
   <plurals name="duration_hours">
-    <item quantity="one" msgid="8917467491248809972">"1 小时"</item>
-    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> 小时"</item>
+    <item quantity="one" msgid="8917467491248809972">"1小时"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>小时"</item>
   </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"视频问题"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"抱歉,该视频不适合在此设备上播放。"</string>
@@ -1183,7 +1183,7 @@
     <string name="capital_on" msgid="1544682755514494298">"开启"</string>
     <string name="capital_off" msgid="6815870386972805832">"关闭"</string>
     <string name="whichApplication" msgid="4533185947064773386">"选择要使用的应用:"</string>
-    <string name="whichApplicationNamed" msgid="8260158865936942783">"需使用%1$s完成操作"</string>
+    <string name="whichApplicationNamed" msgid="8260158865936942783">"使用%1$s完成操作"</string>
     <string name="whichViewApplication" msgid="3272778576700572102">"打开方式"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"使用%1$s打开"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"编辑方式"</string>
@@ -1292,10 +1292,10 @@
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"始终允许"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"永不允许"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"已移除 SIM 卡"</string>
-    <string name="sim_removed_message" msgid="5450336489923274918">"您必须先插入有效的SIM卡再重新开机,然后才能使用移动数据网络。"</string>
+    <string name="sim_removed_message" msgid="5450336489923274918">"您需要先插入有效的SIM卡再重新开机,然后才能使用移动网络。"</string>
     <string name="sim_done_button" msgid="827949989369963775">"完成"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"已添加 SIM 卡"</string>
-    <string name="sim_added_message" msgid="7797975656153714319">"请重新启动您的设备,以便访问移动数据网络。"</string>
+    <string name="sim_added_message" msgid="7797975656153714319">"请重新启动您的设备,以便使用移动网络。"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"重新启动"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"设置时间"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
@@ -1516,7 +1516,7 @@
     <string name="storage_sd_card" msgid="3282948861378286745">"SD 卡"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 存储器"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"修改"</string>
-    <string name="data_usage_warning_title" msgid="1955638862122232342">"流量使用警告"</string>
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"流量警告"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"触摸可查看使用情况和设置。"</string>
     <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
     <skip />
@@ -1534,7 +1534,7 @@
     <skip />
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"超出了 WLAN 数据流量上限"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"超出规定上限 <xliff:g id="SIZE">%s</xliff:g>。"</string>
-    <string name="data_usage_restricted_title" msgid="5965157361036321914">"后台数据受限制"</string>
+    <string name="data_usage_restricted_title" msgid="5965157361036321914">"后台流量受限制"</string>
     <string name="data_usage_restricted_body" msgid="6741521330997452990">"触摸可去除限制。"</string>
     <string name="ssl_certificate" msgid="6510040486049237639">"安全证书"</string>
     <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"该证书有效。"</string>
@@ -1752,25 +1752,16 @@
     <string name="item_is_selected" msgid="949687401682476608">"已选择<xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"已删除<xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
-    <skip />
+    <string name="lock_to_app_toast" msgid="2126866321272822564">"您目前处于单应用模式。要退出,请触摸并按住“最近用过的应用”按钮"</string>
     <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"您目前处于单应用模式。"</string>
     <string name="lock_to_app_title" msgid="5895142291937470019">"要使用“单应用模式”吗?"</string>
-    <!-- no translation found for lock_to_app_description (2800403592608529611) -->
-    <skip />
-    <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
-    <skip />
+    <string name="lock_to_app_description" msgid="2800403592608529611">"“单应用模式”功能会锁定屏幕,使其只显示一个应用。{\n\n要退出,请触摸并按住“最近用过的应用”按钮。"</string>
+    <string name="lock_to_app_negative" msgid="2259143719362732728">"不用了"</string>
     <string name="lock_to_app_positive" msgid="7085139175671313864">"启动"</string>
-    <!-- no translation found for lock_to_app_start (3074665051586318340) -->
-    <skip />
-    <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
-    <skip />
-    <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
-    <skip />
-    <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
-    <skip />
+    <string name="lock_to_app_start" msgid="3074665051586318340">"开启单应用模式"</string>
+    <string name="lock_to_app_exit" msgid="8967089657201849300">"不再使用单应用模式"</string>
+    <string name="lock_to_app_use_screen_lock" msgid="1434584309048590886">"退出前要求%1$s"</string>
+    <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN码"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"解锁图案"</string>
+    <string name="lock_to_app_unlock_password" msgid="795224196583495868">"密码"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 43ab412..8f7b5a0 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允許應用程式修改手機上儲存的瀏覽器記錄或書籤。如此一來,應用程式或可清除或修改瀏覽器資料。注意:這項權限可能不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"設定鬧鐘"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能沒有這項功能。"</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"寫入語音留言"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"允許應用程式修改及移除語音留言收件匣中的訊息。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增留言"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息加到您的留言信箱收件箱。"</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"讀取語音留言"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"允許應用程式讀取您的語音留言。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理資訊權限。惡意應用程式可能會藉此允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"與更新和復原系統互動"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允許應用程式與復原系統和系統更新互動。"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"建立媒體投影工作階段"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"允許應用程式建立媒體投影工作階段。這類工作階段可讓應用程式擷取畫面內容和音訊內容 (一般應用程式並不需用)。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"輕觸兩下即可控制縮放"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"無法新增小工具。"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編輯"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"資料用量警告"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"輕觸即可查看使用量和設定。"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G-3G 數據連線已關閉"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G 數據連線已關閉"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"流動數據連線已關閉"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi 數據連線已關閉"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"已達上限"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"已達 2G-3G 數據上限"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"已達 4G 數據上限"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"已超過流動數據流量上限"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"已達 Wi-Fi 數據上限"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> 超過規定上限。"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"已限制背景資料"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 288b314..fbffc99 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允許應用程式修改手機上儲存的瀏覽紀錄或書籤。這項設定會讓應用程式具有清除或修改瀏覽資料的權限。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"設定鬧鐘"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"寫入語音留言"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"允許應用程式修改及移除語音留言收件匣中的訊息。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增語音留言"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息新增至您的語音信箱收件匣。"</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"讀取語音留言"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"允許應用程式讀取您的語音留言。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理位置權限。請注意,惡意應用程式可能利用此功能允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string>
@@ -1390,10 +1386,8 @@
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"與更新和還原系統互動"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允許應用程式與還原系統及系統更新互動。"</string>
-    <!-- no translation found for permlab_createMediaProjection (4941338725487978112) -->
-    <skip />
-    <!-- no translation found for permdesc_createMediaProjection (1284530992706219702) -->
-    <skip />
+    <string name="permlab_createMediaProjection" msgid="4941338725487978112">"建立媒體投影工作階段"</string>
+    <string name="permdesc_createMediaProjection" msgid="1284530992706219702">"允許應用程式建立媒體投影工作階段。這類工作階段可讓應用程式擷取畫面內容和音訊內容 (一般應用程式並不需要)。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"輕觸兩下即可控制縮放"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"無法新增小工具。"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -1518,20 +1512,14 @@
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編輯"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"資料用量警告"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"輕觸即可查看使用量和設定。"</string>
-    <!-- no translation found for data_usage_3g_limit_title (4462365924791862301) -->
-    <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7476424187522765328) -->
-    <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (3393439305227911006) -->
-    <skip />
-    <!-- no translation found for data_usage_wifi_limit_title (3461968509557554571) -->
-    <skip />
-    <!-- no translation found for data_usage_limit_body (6131350187562939365) -->
-    <skip />
+    <string name="data_usage_3g_limit_title" msgid="4462365924791862301">"2G-3G 數據連線已關閉"</string>
+    <string name="data_usage_4g_limit_title" msgid="7476424187522765328">"4G 數據連線已關閉"</string>
+    <string name="data_usage_mobile_limit_title" msgid="3393439305227911006">"行動數據連線已關閉"</string>
+    <string name="data_usage_wifi_limit_title" msgid="3461968509557554571">"Wi-Fi 數據連線已關閉"</string>
+    <string name="data_usage_limit_body" msgid="6131350187562939365">"已達上限"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"已超過 2G-3G 數據上限"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"已超過 4G 數據上限"</string>
-    <!-- no translation found for data_usage_mobile_limit_snoozed_title (4941346653729943789) -->
-    <skip />
+    <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"已超過行動數據流量上限"</string>
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"已超過 Wi-Fi 數據上限"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> 超過規定上限。"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"已限制背景資料"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index d196a21..7f4e78b 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1006,16 +1006,12 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Ivumela uhlelo lokusebenza ukushintsha umlando wamabhukhimakhi noma wesiphequluli alondolozwe efonini yakho. Lokhu kungavumela uhlelo lokusebenza ukususa noma ukushintsha idatha yesiphequluli. Qaphela: le mvume kungenzeka ingaphoqelelwa iziphequluli ezivela eceleni noma ezinye izinhlelo zokusebenza ezinamandla okuphequlula iwebhu."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"setha i-alamu"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Ivumela uhlelo lokusebenza ukuthi isethe i-alamu ensizeni efkiwe ye-alamu. Ezinye izinhlelo zokusebenza ze-alamu kungenzeka zingakusebenzisi lokho."</string>
-    <!-- no translation found for permlab_writeVoicemail (7309899891683938100) -->
-    <skip />
-    <!-- no translation found for permdesc_writeVoicemail (6592572839715924830) -->
-    <skip />
+    <string name="permlab_writeVoicemail" msgid="7309899891683938100">"bhala ivoyisimeyili"</string>
+    <string name="permdesc_writeVoicemail" msgid="6592572839715924830">"Ivumela uhlelo lokusebenza ukuthi liguqule liphinde lisuse imilayezo esuka kubhokisi lakho lokungenayo lwe-voyisimeyili."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"engeza imeyili yezwi"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ivumela uhlelo lokusebenza ukwengeza imiyalezo kwibhokisi lakho lemeyili yezwi."</string>
-    <!-- no translation found for permlab_readVoicemail (8415201752589140137) -->
-    <skip />
-    <!-- no translation found for permdesc_readVoicemail (8926534735321616550) -->
-    <skip />
+    <string name="permlab_readVoicemail" msgid="8415201752589140137">"funda ivoyisimeyili"</string>
+    <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Ivumela uhlelo lokusebenza ukufunda amavoyisimeyili wakho."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Gugula izimvume zendawo Yesiphequluli"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ivumela uhlelo lokusebenza ukuthi iguqule izimvume eziphathelene nezindawo Zesiphequluli. Izuhlelo lokusebenza eziyingozi zingasebenzisa lokhu ukuvumela ukuvumela imininingwane yendawo kunoma imaphi amawebusayithi."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"qinisekisa amaphakheji"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f69ab0f..73c6a67 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4185,6 +4185,8 @@
         <attr name="dropDownSelector" />
         <!-- Background drawable to use for the dropdown in spinnerMode="dropdown". -->
         <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" />
@@ -5468,11 +5470,9 @@
              Corresponds to {@link android.transition.Visibility#setMode(int)}. -->
         <attr name="visibilityMode">
             <!-- Only appearing Views will be supported. -->
-            <enum name="mode_in" value="1" />
+            <flag name="mode_in" value="1" />
             <!-- Only disappearing Views will be supported. -->
-            <enum name="mode_out" value="2" />
-            <!-- Both appearing and disappearing views will be supported. -->
-            <enum name="mode_in_out" value="3" />
+            <flag name="mode_out" value="2" />
         </attr>
     </declare-styleable>
     <!-- Use <code>target</code> as the root tag of the XML resource that
@@ -6898,6 +6898,9 @@
         <attr name="contentInsetRight" format="dimension" />
         <!-- Elevation for the action bar itself -->
         <attr name="elevation" />
+        <!-- Reference to a theme that should be used to inflate popups
+             shown by widgets in the action bar. -->
+        <attr name="popupTheme" />
     </declare-styleable>
 
     <declare-styleable name="ActionMode">
@@ -7186,6 +7189,9 @@
             <flag name="bottom" value="0x50" />
         </attr>
         <attr name="collapseIcon" format="reference" />
+        <!-- Reference to a theme that should be used to inflate popups
+             shown by widgets in the toolbar. -->
+        <attr name="popupTheme" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="Toolbar_LayoutParams">
@@ -7213,24 +7219,6 @@
              the settings for this service. -->
         <attr name="settingsActivity" />
         <!-- Type of this service. -->
-        <attr name="tvInputType">
-            <!-- Should be in sync with constant values defined in
-                 {@link android.media.tv.TvInputInfo}. -->
-
-            <!-- Virtual input (default) -->
-            <enum name="virtual" value="0" />
-
-            <enum name="otherHardware" value="1" />
-            <enum name="tuner" value="2" />
-            <enum name="composite" value="3" />
-            <enum name="svideo" value="4" />
-            <enum name="scart" value="5" />
-            <enum name="component" value="6" />
-            <enum name="vga" value="7" />
-            <enum name="dvi" value="8" />
-            <enum name="hdmi" value="9" />
-            <enum name="displayPort" value="10" />
-        </attr>
     </declare-styleable>
 
     <declare-styleable name="ResolverDrawerLayout">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3026514..7311a60 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -212,6 +212,9 @@
         <!-- Additional flag from base permission type: this permission can also
              (optionally) be granted to development applications. -->
         <flag name="development" value="0x20" />
+        <!-- Additional flag from base permission type: this permission is closely
+             associated with an app op for controlling access. -->
+        <flag name="appop" value="0x40" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a441382..a6e85e9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2097,7 +2097,6 @@
   <public type="attr" name="isGame" id="0x10103f4" />
   <public type="attr" name="allowEmbedded" id="0x10103f5" />
   <public type="attr" name="setupActivity" id="0x10103f6"/>
-  <public type="attr" name="tvInputType" id="0x10103f7"/>
 
 <!-- ===============================================================
      Resources added in version 21 of the platform
@@ -2267,6 +2266,8 @@
   <public type="attr" name="searchKeyphraseRecognitionFlags" />
   <public type="attr" name="checkMarkTint" />
   <public type="attr" name="checkMarkTintMode" />
+  <public type="attr" name="popupTheme" />
+  <public type="attr" name="toolbarStyle" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0d9da35..b41e37c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -774,6 +774,12 @@
        about currently and recently running tasks.  This may allow the app to
        discover information about which applications are used on the device.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_startTasksFromRecents">start a task from recents</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_startTasksFromRecents">Allows the app to use an ActivityManager.RecentTaskInfo
+        object to launch a defunct task that was returned from ActivityManager.getRecentTaskList().</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
     <string name="permlab_interactAcrossUsers">interact across users</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 575bbe8..a8974c6 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -543,6 +543,7 @@
     <style name="Widget.Material.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
         <item name="dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
         <item name="popupBackground">@drawable/popup_background_material</item>
+        <item name="popupElevation">@dimen/floating_window_z</item>
     </style>
 
     <style name="Widget.Material.CompoundButton" parent="Widget.CompoundButton"/>
@@ -663,6 +664,7 @@
 
     <style name="Widget.Material.PopupWindow.ActionMode">
         <item name="popupBackground">@drawable/popup_background_material</item>
+        <item name="popupElevation">@dimen/floating_window_z</item>
         <item name="popupAnimationStyle">@style/Animation.PopupWindow.ActionMode</item>
     </style>
 
@@ -731,6 +733,7 @@
         <item name="background">@drawable/spinner_background_material</item>
         <item name="dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
         <item name="popupBackground">@drawable/popup_background_material</item>
+        <item name="popupElevation">@dimen/floating_window_z</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
@@ -863,14 +866,15 @@
         <item name="divider">?attr/dividerVertical</item>
         <item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionBar.Subtitle</item>
-        <item name="progressBarStyle">@style/Widget.Material.ProgressBar.Horizontal</item>
-        <item name="indeterminateProgressStyle">@style/Widget.Material.ProgressBar</item>
+        <item name="progressBarStyle">?attr/progressBarStyleHorizontal</item>
+        <item name="indeterminateProgressStyle">?attr/progressBarStyle</item>
         <item name="progressBarPadding">32dip</item>
         <item name="itemPadding">8dip</item>
         <item name="homeLayout">@layout/action_bar_home_material</item>
         <item name="gravity">center_vertical</item>
         <item name="contentInsetStart">16dp</item>
         <item name="elevation">8dp</item>
+        <item name="popupTheme">?attr/actionBarPopupTheme</item>
     </style>
 
     <style name="Widget.Material.ActionBar.Solid">
@@ -1032,23 +1036,8 @@
     <style name="Widget.Material.Light.ActionBar.TabText" parent="Widget.Material.ActionBar.TabText"/>
     <style name="Widget.Material.Light.ActionMode" parent="Widget.Material.ActionMode" />
     <style name="Widget.Material.Light.ActionButton.CloseMode" parent="Widget.Material.ActionButton.CloseMode" />
-
-    <style name="Widget.Material.Light.ActionBar" parent="Widget.Material.ActionBar">
-        <item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionBar.Title</item>
-        <item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionBar.Subtitle</item>
-        <item name="background">@null</item>
-        <item name="backgroundStacked">@null</item>
-        <item name="backgroundSplit">@null</item>
-        <item name="progressBarStyle">@style/Widget.Material.Light.ProgressBar.Horizontal</item>
-        <item name="indeterminateProgressStyle">@style/Widget.Material.Light.ProgressBar</item>
-    </style>
-
-    <style name="Widget.Material.Light.ActionBar.Solid">
-        <item name="background">?attr/colorPrimary</item>
-        <item name="backgroundStacked">?attr/colorPrimary</item>
-        <item name="backgroundSplit">?attr/colorPrimary</item>
-    </style>
-
+    <style name="Widget.Material.Light.ActionBar" parent="Widget.Material.ActionBar" />
+    <style name="Widget.Material.Light.ActionBar.Solid" parent="Widget.Material.ActionBar.Solid" />
     <style name="Widget.Material.Light.FastScroll" parent="Widget.Material.FastScroll"/>
     <style name="Widget.Material.Light.MediaRouteButton" parent="Widget.Material.MediaRouteButton" />
 
diff --git a/docs/html/about/versions/android-4.2.jd b/docs/html/about/versions/android-4.2.jd
index 73d51c5..76acb8a 100644
--- a/docs/html/about/versions/android-4.2.jd
+++ b/docs/html/about/versions/android-4.2.jd
@@ -361,8 +361,7 @@
 href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a>.</p>
 
 <p>Beware that if your app requests one of the hardware device identifiers (such as the WiFi MAC
-address, the {@link android.os.Build#SERIAL} number, or the {@link
-android.provider.Settings.Secure#ANDROID_ID} number), they will provide the same value for each
+address or the {@link android.os.Build#SERIAL} number), they will provide the same value for each
 user because these identifiers are tied to the hardware and not the user. Not to mention the other
 problems these identifiers introduce as discussed in the <a
 href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">Identifying
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index eec4e8d..1664923 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -90,10 +90,10 @@
   </div>
   <div class="layout-content-col span-4">
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Toolkit AI']);"
-    href="{@docRoot}downloads/design/Android_Wear_Toolkit_20140626.ai">Adobe&reg; Illustrator&reg; Toolkit</a>
+    href="{@docRoot}downloads/design/Android_Wear_Toolkit_20140722.ai">Adobe&reg; Illustrator&reg; Toolkit</a>
 
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Toolkit PDF']);"
-    href="{@docRoot}downloads/design/Android_Wear_Toolkit_20140626.pdf">PDF Toolkit</a>
+    href="{@docRoot}downloads/design/Android_Wear_Toolkit_20140722.pdf">PDF Toolkit</a>
   </div>
 </div>
 
@@ -111,9 +111,9 @@
   </div>
   <div class="layout-content-col span-4">
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear App Patterns AI']);"
-    href="{@docRoot}downloads/design/Android_Wear_Patterns_20140626.ai">Adobe&reg; Illustrator&reg; App Patterns</a>
+    href="{@docRoot}downloads/design/Android_Wear_Patterns_20140722.ai">Adobe&reg; Illustrator&reg; App Patterns</a>
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear App Patterns PDF']);"
-    href="{@docRoot}downloads/design/Android_Wear_Patterns_20140626.pdf">PDF App Patterns</a>
+    href="{@docRoot}downloads/design/Android_Wear_Patterns_20140722.pdf">PDF App Patterns</a>
   </div>
 </div>
 
diff --git a/docs/html/guide/topics/text/creating-input-method.jd b/docs/html/guide/topics/text/creating-input-method.jd
index 205fd96..4b6b7b7 100644
--- a/docs/html/guide/topics/text/creating-input-method.jd
+++ b/docs/html/guide/topics/text/creating-input-method.jd
@@ -4,6 +4,30 @@
 
 <div id="qv-wrapper">
 <div id="qv">
+<h2>In This Document</h2>
+<ol>
+    <li>
+        <a href="#InputMethodLifecycle">The IME Lifecycle</a>
+    </li>
+    <li>
+        <a href="#DefiningIME">Declaring IME Components in the Manifest</a>
+    </li>
+    <li>
+        <a href="#IMEAPI">The Input Method API</a>
+    </li>
+    <li>
+        <a href="#IMEUI">Designing the Input Method UI</a>
+    </li>
+    <li>
+        <a href="#SendText">Sending Text to the Application</a>
+    </li>
+    <li>
+        <a href="#IMESubTypes">Creating an IME Subtype</a>
+    </li>
+    <li>
+        <a href="#GeneralDesign">General IME Considerations</a>
+    </li>
+</ol>
 <h2>See also</h2>
 <ol>
     <li>
@@ -16,29 +40,20 @@
 </div>
 </div>
 <p>
-    An input method editor (IME) is a user control that enables users to enter text. Android 
-    provides an extensible input method framework that allows applications to provide users 
-    alternative input methods, such as on-screen keyboards or even speech input. Once installed, 
-    users can select which IME they want to use from the system settings and use it across the 
+    An input method editor (IME) is a user control that enables users to enter text. Android
+    provides an extensible input method framework that allows applications to provide users
+    alternative input methods, such as on-screen keyboards or even speech input. Once installed,
+    users can select which IME they want to use from the system settings and use it across the
     entire system; only one IME may be enabled at a time.
 </p>
 <p>
     To add an IME to the Android system, you create an Android application
-    containing a class that extends {@link android.inputmethodservice.InputMethodService}. In 
+    containing a class that extends {@link android.inputmethodservice.InputMethodService}. In
     addition, you usually create a "settings" activity that passes options to the IME
     service. You can also define a settings UI that's displayed as part of the system settings.
 </p>
-<p>This article covers the following:</p>
-<ul>
-    <li>The IME lifecycle.</li>
-    <li>Declaring IME components in the application manifest.</li>
-    <li>The IME API.</li>
-    <li>Designing an IME UI.</li>
-    <li>Sending text from an IME to an application.</li>
-    <li>Working with IME subtypes.</li>
-</ul>
 <p>
-    If you haven't worked with IMEs before, you should read the introductory article 
+    If you haven't worked with IMEs before, you should read the introductory article
     <a href="http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html">Onscreen Input Methods</a> first.
     Also, the Soft Keyboard sample app included in the SDK contains sample code that you can modify
     to start building your own IME.
@@ -59,16 +74,16 @@
 <h2 id="DefiningIME">Declaring IME Components in the Manifest</h2>
 <p>
     In the Android system, an IME is an Android application that contains a special IME service.
-    The application's manifest file must declare the service, request the necessary permissions, 
-    provide an intent filter that matches the action <code>action.view.InputMethod</code>, and 
+    The application's manifest file must declare the service, request the necessary permissions,
+    provide an intent filter that matches the action <code>action.view.InputMethod</code>, and
     provide metadata that defines characteristics of the IME. In addition, to provide a settings
     interface that allows the user to modify the behavior of the IME, you can define a "settings"
     activity that can be launched from System Settings.
 </p>
 <p>
     The following snippet declares IME service. It requests the permission {@link
-    android.Manifest.permission#BIND_INPUT_METHOD} to allow the service to connect the IME to 
-    the system, sets up an intent filter that matches the action 
+    android.Manifest.permission#BIND_INPUT_METHOD} to allow the service to connect the IME to
+    the system, sets up an intent filter that matches the action
     <code>android.view.InputMethod</code>, and defines metadata for the IME:
 </p>
 <pre>
@@ -88,7 +103,7 @@
     for the IME application:</p>
 <pre>
     &lt;!-- Optional: an activity for controlling the IME settings --&gt;
-    &lt;activity android:name="FastInputIMESettings" 
+    &lt;activity android:name="FastInputIMESettings"
         android:label="&#64;string/fast_input_settings"&gt;
         &lt;intent-filter&gt;
             &lt;action android:name="android.intent.action.MAIN"/&gt;
@@ -105,12 +120,12 @@
     handling keyboard characters.
 </p>
 <p>
-    The central part of an IME is a service component, a class that extends 
-    {@link android.inputmethodservice.InputMethodService}. In addition to implementing the 
-    normal service lifecycle, this class has callbacks for providing your IME's UI, handling user 
+    The central part of an IME is a service component, a class that extends
+    {@link android.inputmethodservice.InputMethodService}. In addition to implementing the
+    normal service lifecycle, this class has callbacks for providing your IME's UI, handling user
     input, and delivering text to the field that currently has focus. By default, the
-    {@link android.inputmethodservice.InputMethodService} class provides most of the implementation 
-    for managing the state and visibility of the IME and communicating with the current 
+    {@link android.inputmethodservice.InputMethodService} class provides most of the implementation
+    for managing the state and visibility of the IME and communicating with the current
     input field.
 </p>
 <p>
@@ -122,13 +137,13 @@
         Defines the communication channel from an {@link android.view.inputmethod.InputMethod}
         back to the application that is receiving its input. You use it to read text around the
         cursor, commit text to the text box, and send raw key events to the application.
-        Applications should extend this class rather than implementing the base interface 
+        Applications should extend this class rather than implementing the base interface
         {@link android.view.inputmethod.InputConnection}.
     </dd>
     <dt>{@link android.inputmethodservice.KeyboardView}</dt>
     <dd>
         An extension of {@link android.view.View} that renders a keyboard and responds to user
-        input events. The keyboard layout is specified by an instance of 
+        input events. The keyboard layout is specified by an instance of
         {@link android.inputmethodservice.Keyboard}, which you can define in an XML file.
     </dd>
 </dl>
@@ -141,40 +156,40 @@
 <h3 id="InputView">Input view</h3>
 <p>
     The input view is the UI where the user inputs text, in the form of keyclicks, handwriting or
-    gestures. When the iIME is displayed for the first time, the system calls the 
+    gestures. When the iIME is displayed for the first time, the system calls the
     {@link android.inputmethodservice.InputMethodService#onCreateInputView()} callback. In your
     implementation of this method, you create the layout you want to display in the IME
     window and return the layout to the system. This snippet is an example of implementing the
     {@link android.inputmethodservice.InputMethodService#onCreateInputView()} method:
 <pre>
-    &#64;Override 
-    public View onCreateInputView() { 
-        MyKeyboardView inputView = 
+    &#64;Override
+    public View onCreateInputView() {
+        MyKeyboardView inputView =
             (MyKeyboardView) getLayoutInflater().inflate( R.layout.input, null);
-    
-        inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(mLatinKeyboard); 
-        
-        return mInputView; 
-    } 
+
+        inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(mLatinKeyboard);
+
+        return mInputView;
+    }
 </pre>
 <p>
-    In this example, {@code MyKeyboardView} is an instance of a custom implementation of 
-    {@link android.inputmethodservice.KeyboardView} that renders a 
-    {@link android.inputmethodservice.Keyboard}. If you’re building a traditional QWERTY keyboard, 
-    see the  Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample 
+    In this example, {@code MyKeyboardView} is an instance of a custom implementation of
+    {@link android.inputmethodservice.KeyboardView} that renders a
+    {@link android.inputmethodservice.Keyboard}. If you’re building a traditional QWERTY keyboard,
+    see the  Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample
     app</a> for an example of how to extend the {@link android.inputmethodservice.KeyboardView} class.
 </p>
 <h3 id="CandidateView">Candidates view</h3>
 <p>
     The candidates view is the UI where the IME displays potential word corrections or
-    suggestions for the user to select. In the IME lifecycle, the system calls 
-    {@link android.inputmethodservice.InputMethodService#onCreateCandidatesView()} when it's ready 
+    suggestions for the user to select. In the IME lifecycle, the system calls
+    {@link android.inputmethodservice.InputMethodService#onCreateCandidatesView()} when it's ready
     to display the candidate view. In your implementation of this method, return a layout that shows
     word suggestions, or return null if you don’t want to show anything (a null response is the
     default behavior, so you don’t have to implement this if you don’t provide suggestions).</p>
 <p>
-    For an example implementation that provides user suggestions, see the 
-    Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample 
+    For an example implementation that provides user suggestions, see the
+    Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample
     app</a>.
 </p>
 <h3 id="DesignConsiderations">UI design considerations</h3>
@@ -209,10 +224,10 @@
     <strong>Figure 2.</strong> Latin IME input types.
 </p>
 <p>
-    When an input field receives focus and your IME starts, the system calls 
+    When an input field receives focus and your IME starts, the system calls
     {@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean)
-    onStartInputView()}, passing in an {@link android.view.inputmethod.EditorInfo} object that 
-    contains details about the input type and other attributes of the text field. In this object, 
+    onStartInputView()}, passing in an {@link android.view.inputmethod.EditorInfo} object that
+    contains details about the input type and other attributes of the text field. In this object,
     the {@link android.view.inputmethod.EditorInfo#inputType} field contains the text field's input
     type.
 </p>
@@ -223,7 +238,7 @@
     this:
 </p>
 <pre>
-inputType &amp; InputType.TYPE_MASK_CLASS 
+inputType &amp; InputType.TYPE_MASK_CLASS
 </pre>
 <p>
 The input type bit pattern can have one of several values, including:
@@ -248,7 +263,7 @@
     </dd>
 </dl>
 <p>
-    These constants are described in more detail in the reference documentation for 
+    These constants are described in more detail in the reference documentation for
     {@link android.text.InputType}.
 </p>
 <p>
@@ -287,8 +302,8 @@
 <p>
     As the user inputs text with your IME, you can send text to the application by
     sending individual key events or by editing the text around the cursor in the application's text
-    field. In either case, you use an instance of {@link android.view.inputmethod.InputConnection} 
-    to deliver the text. To get this instance, call 
+    field. In either case, you use an instance of {@link android.view.inputmethod.InputConnection}
+    to deliver the text. To get this instance, call
     {@link android.inputmethodservice.InputMethodService#getCurrentInputConnection
     InputMethodService.getCurrentInputConnection()}.
 </p>
@@ -336,18 +351,18 @@
 </p>
 <pre>
     InputConnection ic = getCurrentInputConnection();
-    
+
     ic.deleteSurroundingText(4, 0);
-    
+
     ic.commitText("Hello", 1);
-    
+
     ic.commitText("!", 1);
 </pre>
 <h3 id="ComposeThenCommit">Composing text before committing</h3>
 <p>
     If your IME does text prediction or requires multiple steps to compose a glyph or
     word, you can show the progress in the text field until the user commits the word, and then you
-    can replace the partial composition with the completed text. You may give special treatment to 
+    can replace the partial composition with the completed text. You may give special treatment to
     the text by adding a "span" to it when you pass it to InputConnection#setComposingText().
 </p>
 <p>
@@ -385,10 +400,10 @@
     selection during composition. You may also want to trap the back key to dismiss any popups
     originating from the input method window.</p>
 <p>
-    To intercept hardware keys, override 
+    To intercept hardware keys, override
     {@link android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent) onKeyDown()}
-    and {@link android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent) onKeyUp()}. 
-    See the Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample 
+    and {@link android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent) onKeyUp()}.
+    See the Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample
     app</a> for an example.
 </p>
 <p>
@@ -396,7 +411,7 @@
 </p>
 <h2 id="IMESubTypes">Creating an IME Subtype</h2>
 <p>
-    Subtypes allow the IME to expose multiple input modes and languages supported by an IME. A 
+    Subtypes allow the IME to expose multiple input modes and languages supported by an IME. A
     subtype can represent:
 </p>
 <ul>
@@ -414,13 +429,13 @@
 <p>
     Subtype information is used for an IME switcher dialog that's available from the notification
     bar and also for IME settings. The information also allows the framework to bring up a
-    specific subtype of an IME directly. When you build an IME, use the subtype facility, because 
+    specific subtype of an IME directly. When you build an IME, use the subtype facility, because
     it helps the user identify and switch between different IME languages and modes.
 </p>
 <p>
     You define subtypes in one of the input method's XML resource files, using the
-    <code>&lt;subtype&gt;</code> element. The following snippet defines an IME with two 
-    subtypes: a keyboard subtype for the US English locale, and another keyboard subtype for the 
+    <code>&lt;subtype&gt;</code> element. The following snippet defines an IME with two
+    subtypes: a keyboard subtype for the US English locale, and another keyboard subtype for the
     French language locale for France:
 </p>
 <pre>
@@ -457,8 +472,8 @@
         android:imeSubtypeMode="keyboard" /&gt;
 </pre>
 <p>
-    The next snippet is part of the IME's <code>strings.xml</code> file. The string 
-    resource <code>label_subtype_generic</code>, which is used by the input method UI definition to 
+    The next snippet is part of the IME's <code>strings.xml</code> file. The string
+    resource <code>label_subtype_generic</code>, which is used by the input method UI definition to
     set the subtype's label, is defined as:
 </p>
 <pre>
@@ -487,9 +502,9 @@
 <h3 id="SubtypeSettings">Choosing IME subtypes from System Settings</h3>
 <p>
     A user can control how subtypes are used in the “Language &amp; input” settings panel in the
-    System Settings area. In the Soft Keyboard sample, the file 
-    <code>InputMethodSettingsFragment.java</code> contains an implementation that 
-    facilitates a subtype enabler in the IME settings. Please refer to the SoftKeyboard sample in 
+    System Settings area. In the Soft Keyboard sample, the file
+    <code>InputMethodSettingsFragment.java</code> contains an implementation that
+    facilitates a subtype enabler in the IME settings. Please refer to the SoftKeyboard sample in
     the Android SDK for more information about how to support Input Method Subtypes in your IME.
 </p>
 <img src="{@docRoot}resources/articles/images/inputmethod_subtype_settings.png" alt=""
@@ -497,6 +512,7 @@
 <p class="img-caption">
     <strong>Figure 6.</strong> Choosing a language for the IME.
 </p>
+
 <h2 id="GeneralDesign">General IME Considerations</h2>
 <p>
     Here are some other things to consider as you're implementing your IME:
@@ -506,22 +522,22 @@
     Provide a way for users to set options directly from the IME's UI.
 </li>
 <li>
-    Because multiple IMEs may be installed on the device, provide a way for the user to switch to a 
+    Because multiple IMEs may be installed on the device, provide a way for the user to switch to a
     different IME directly from the input method UI.
 </li>
 <li>
-    Bring up the IME's UI quickly. Preload or load on demand any large resources so that users 
-    see the IME as soon as they tap on a text field. Cache resources and views for subsequent 
+    Bring up the IME's UI quickly. Preload or load on demand any large resources so that users
+    see the IME as soon as they tap on a text field. Cache resources and views for subsequent
     invocations of the input method.
 </li>
 <li>
-    Conversely, you should release large memory allocations soon after the input method window is 
+    Conversely, you should release large memory allocations soon after the input method window is
     hidden, so that applications can have sufficient memory to run. Consider using a delayed message
     to release resources if the IME is in a hidden state for a few seconds.
-</li>    
+</li>
 <li>
-    Make sure that users can enter as many characters as possible for the language or locale 
-    associated with the IME. Remember that users may use punctuation in passwords or user 
+    Make sure that users can enter as many characters as possible for the language or locale
+    associated with the IME. Remember that users may use punctuation in passwords or user
     names, so your IME has to provide many different characters to allow users to enter a
     password and get access to the device.
 </li>
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 88bc733..864e82e 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -28,8 +28,7 @@
       <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included
 in most Eclipse IDE packages) </li>
       <li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">JDK 6</a>
-        (JRE alone is not sufficient)</li>oid Development Tools plugin</a>
-(recommended)</li>
+        (JRE alone is not sufficient)</li>
       <li><strong>Not</strong> compatible with GNU Compiler for Java (gcj)</li>
     </ul>
 
@@ -79,73 +78,6 @@
 <a href="{@docRoot}sdk/installing/adding-packages.html">Adding Platforms and Packages</a>.</p>
 
 
-<h2 id="tmgr">Download the ADT Translation Manager Plugin</h2>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>App Translations in Google Play</h2>
-<p>Google Play <a href="{@docRoot}distribute/tools/localization-checklist.html#gp-trans">App
-Translation Service</a> is available in the Developer Console to help you
-localize your app for a global user base. You can browse qualified vendors, get
-estimates, upload strings for translation, and then import the translations directly
-into your app.</p>
-</div>
-</div>
-
-<p>ADT Translation Manager Plugin is an Android SDK Tools plugin that helps
-you work with strings that you are localizing. It's designed to work
-with the translation services built into the Google Play Developer
-Console that let you quickly find and purchase translations of
-your app from a list of pre-qualified vendors. </p>
-
-<p>The plugin simplifies the management of strings
-during translation. It lets you easily export your default strings
-and upload them directly to the Developer Console, from which you
-can get estimates or purchase translations. When your translations
-are ready, the plugin lets you quickly download and import them
-back into your project. During import, it moves all of the translated resources into
-the correct locations under <code>res/values</code>, so that
-localization works instantly.</p>
-
-<p>For more information about translation services in Google Play, see <a
-href="{@docRoot}distribute/tools/localization-checklist.html#gp-trans">Purchase
-professional translations through the Developer Console</a>.</p>
-
-<p>To install the ADT Translation Manager Plugin follow these steps:</p>
-
-<ol>
-    <li>Install the ADT Plugin, as described above. </li>
-    <li>In Eclipse, select <strong>Help</strong> &gt; <strong>Install New
-Software</strong>.</li>
-    <li>Click <strong>Add</strong>, in the top-right corner.</li>
-    <li>In the Add Repository dialog that appears, enter a repository name for the <em>Name</em>
-      and the following URL for the <em>Location</em>:
-      <pre>https://dl.google.com/alt/</pre>
-    </li>
-    <li>Click <strong>OK</strong>.
-    <li>In the Available Software dialog, select the checkbox next to <strong>Android Developer Tools
-       - Translation Manager</strong> and click <strong>Next</strong>.</li>
-    <li>In the next window, you'll see a list of the tools to be downloaded. Click
-<strong>Next</strong>. </li>
-    <li>Read and accept the license agreements, then click <strong>Finish</strong>.
-      <p>If you get a security warning saying that the authenticity or validity of
-the software can't be established, click <strong>OK</strong>.</p></li>
-    <li>When the installation completes, restart Eclipse. </li>
-</ol>
-
-<h4 id="translation-manager-notes">Installation notes</h4>
-
-<ul>
-<li>The full ADT Plugin must be installed in your Eclipse environment before you install the ADT Translation Manager Plugin.</li>
-<li>ADT Translation Manager Plugin is designed for use with the translation services offered through the Google Play Developer Console. It is not designed for general purpose import/export of strings. </li>
-<li>To use the plugin, you must <a href="{@docRoot}distribute/googleplay/start.html">set up a Developer Console account</a>. </li>
-<li>Currently, translation services are available through the Developer Console only as part of a pilot program. To use the plugin, you must first sign up for the pilot program by visiting the Developer Console.</li>
-<li>If you downloaded ADT as part of the SDK ADT bundle, you may encounter an error when attempting to download the ADT Translation Manager Plugin from the remote repository. In that case, open the <strong>Install New
-Software</strong>, uncheck "Contact all update sites during install to find required software" at the bottom and try again. </li>
-</ul>
-
-
-
 <h2 id="Troubleshooting">Troubleshooting ADT Installation</h2>
 
 <p>If you are having trouble downloading the ADT plugin after following the
diff --git a/docs/html/training/notepad/index.jd b/docs/html/training/notepad/index.jd
index d1aa221..507b232 100644
--- a/docs/html/training/notepad/index.jd
+++ b/docs/html/training/notepad/index.jd
@@ -17,13 +17,9 @@
 application. The exercises explain each step in detail and provide all the 
 sample code you need to complete the application. </p>
 
-<p>When you are finished with the tutorial, you will have created a functioning
+<p><p>When you are finished with the tutorial, you will have created a functioning
 Android application and will have learned many of the most important
-concepts in Android development. If you want to add more complex features to
-your application, you can examine the code in an alternative implementation
-of a Note Pad application, in the 
-<a href="{@docRoot}resources/samples/index.html">Sample Code</a> section. </p>
-
+concepts in Android development.</p>
 
 <a name="who"></a>
 <h2>Who Should Use this Tutorial</h2>
@@ -122,17 +118,13 @@
 <li>For a lighter but broader introduction to concepts not covered in the
 tutorial,
 take a look at <a href="{@docRoot}resources/faq/commontasks.html">Common Android Tasks</a>.</li>
-<li>The Android SDK includes a variety of fully functioning sample applications
-that make excellent opportunities for further learning. You can find the sample
-applications in the <code>samples/</code> directory of your downloaded SDK, or browser them
-here, in the <a href="{@docRoot}resources/samples/index.html">Sample Code</a> section.</li>
+
 <li>This tutorial draws from the full Notepad application included in the
-<code>samples/</code> directory of the SDK, though it does not match it exactly. 
-When you are done with the tutorial,
-it is highly recommended that you take a closer look at this version of the Notepad
-application, 
-as it demonstrates a variety of interesting additions for your application, 
-such as:</li>
+<code>samples/legacy/NotePad</code> directory of the SDK, though it does not
+match it exactly. When you are done with the tutorial, it is highly recommended
+that you take a closer look at this version of the Notepad application, as it
+demonstrates a variety of interesting additions for your application, such
+as:</li>
   <ul>
     <li>Setting up a custom striped list for the list of notes.</li>
     <li>Creating a custom text edit view that overrides the <code>draw()</code>
diff --git a/docs/html/training/wearables/apps/voice.jd b/docs/html/training/wearables/apps/voice.jd
index 3dea5d7..639d90a 100644
--- a/docs/html/training/wearables/apps/voice.jd
+++ b/docs/html/training/wearables/apps/voice.jd
@@ -263,7 +263,7 @@
 &#64;Override
 protected void onActivityResult(int requestCode, int resultCode,
         Intent data) {
-    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
+    if (requestCode == SPEECH_REQUEST_CODE && resultCode == RESULT_OK) {
         List&lt;String&gt; results = data.getStringArrayListExtra(
                 RecognizerIntent.EXTRA_RESULTS);
         String spokenText = results.get(0);
@@ -271,4 +271,4 @@
     }
     super.onActivityResult(requestCode, resultCode, data);
 }
-</pre>
\ No newline at end of file
+</pre>
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 1709558..3a4c2a7 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -155,6 +155,11 @@
      * Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)}
      */
     public void setRoundRect(int left, int top, int right, int bottom, float radius) {
+        if (left >= right || top >= bottom) {
+            setEmpty();
+            return;
+        }
+
         if (mRect == null) mRect = new Rect();
         mRect.set(left, top, right, bottom);
         mRadius = radius;
@@ -173,11 +178,17 @@
      * Sets the outline to the oval defined by input rect.
      */
     public void setOval(int left, int top, int right, int bottom) {
+        if (left >= right || top >= bottom) {
+            setEmpty();
+            return;
+        }
+
         if ((bottom - top) == (right - left)) {
             // represent circle as round rect, for efficiency, and to enable clipping
             setRoundRect(left, top, right, bottom, (bottom - top) / 2.0f);
             return;
         }
+
         if (mPath == null) mPath = new Path();
         mPath.reset();
         mPath.addOval(left, top, right, bottom, Path.Direction.CW);
@@ -196,6 +207,11 @@
      * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}.
      */
     public void setConvexPath(@NonNull Path convexPath) {
+        if (convexPath.isEmpty()) {
+            setEmpty();
+            return;
+        }
+
         if (!convexPath.isConvex()) {
             throw new IllegalArgumentException("path must be convex");
         }
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 024bdfd..83426e8 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -49,15 +49,20 @@
         mBounds.set(outline->getBounds());
     }
 
-    bool isEmpty() const {
-        return mType == kOutlineType_None;
+    void setEmpty() {
+        mType = kOutlineType_Empty;
+        mPath.reset();
     }
 
-    void setEmpty() {
+    void setNone() {
         mType = kOutlineType_None;
         mPath.reset();
     }
 
+    bool isEmpty() const {
+        return mType == kOutlineType_Empty;
+    }
+
     void setShouldClip(bool clip) {
         mShouldClip = clip;
     }
@@ -81,7 +86,7 @@
     }
 
     const SkPath* getPath() const {
-        if (mType == kOutlineType_None) return NULL;
+        if (mType == kOutlineType_None || mType == kOutlineType_Empty) return NULL;
 
         return &mPath;
     }
@@ -89,8 +94,9 @@
 private:
     enum OutlineType {
         kOutlineType_None = 0,
-        kOutlineType_ConvexPath = 1,
-        kOutlineType_RoundRect = 2
+        kOutlineType_Empty = 1,
+        kOutlineType_ConvexPath = 2,
+        kOutlineType_RoundRect = 3
     };
 
     bool mShouldClip;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index fe03806..3eb779f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -581,7 +581,7 @@
 
 template <class T>
 void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) {
-    if (properties().getAlpha() <= 0.0f || properties().getOutline().isEmpty()) return;
+    if (properties().getAlpha() <= 0.0f || !properties().getOutline().getPath()) return;
 
     mat4 shadowMatrixXY(transformFromParent);
     applyViewPropertyTransforms(shadowMatrixXY);
@@ -776,16 +776,23 @@
  */
 template <class T>
 void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
+    const int level = handler.level();
+    if (mDisplayListData->isEmpty()) {
+        DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName());
+        return;
+    }
+
     const bool drawLayer = (mLayer && (&renderer != mLayer->renderer));
     // If we are updating the contents of mLayer, we don't want to apply any of
     // the RenderNode's properties to this issueOperations pass. Those will all
     // be applied when the layer is drawn, aka when this is true.
     const bool useViewProperties = (!mLayer || drawLayer);
-
-    const int level = handler.level();
-    if (mDisplayListData->isEmpty() || (useViewProperties && properties().getAlpha() <= 0)) {
-        DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName());
-        return;
+    if (useViewProperties) {
+        const Outline& outline = properties().getOutline();
+        if (properties().getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty())) {
+            DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", level * 2, "", this, getName());
+            return;
+        }
     }
 
     handler.startMark(getName());
diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java
index 2272ac3..591a6ca 100644
--- a/location/java/android/location/GpsMeasurement.java
+++ b/location/java/android/location/GpsMeasurement.java
@@ -33,6 +33,7 @@
     private double mTimeOffsetInNs;
     private short mState;
     private long mReceivedGpsTowInNs;
+    private long mReceivedGpsTowUncertaintyInNs;
     private double mCn0InDbHz;
     private double mPseudorangeRateInMetersPerSec;
     private double mPseudorangeRateUncertaintyInMetersPerSec;
@@ -171,6 +172,7 @@
         mTimeOffsetInNs = measurement.mTimeOffsetInNs;
         mState = measurement.mState;
         mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs;
+        mReceivedGpsTowUncertaintyInNs = measurement.mReceivedGpsTowUncertaintyInNs;
         mCn0InDbHz = measurement.mCn0InDbHz;
         mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
         mPseudorangeRateUncertaintyInMetersPerSec =
@@ -318,6 +320,20 @@
     }
 
     /**
+     * Gets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
+     */
+    public long getReceivedGpsTowUncertaintyInNs() {
+        return mReceivedGpsTowUncertaintyInNs;
+    }
+
+    /**
+     * Sets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
+     */
+    public void setReceivedGpsTowUncertaintyInNs(long value) {
+        mReceivedGpsTowUncertaintyInNs = value;
+    }
+
+    /**
      * Gets the Carrier-to-noise density in dB-Hz.
      * Range: [0, 63].
      *
@@ -1129,6 +1145,7 @@
             gpsMeasurement.mTimeOffsetInNs = parcel.readDouble();
             gpsMeasurement.mState = (short) parcel.readInt();
             gpsMeasurement.mReceivedGpsTowInNs = parcel.readLong();
+            gpsMeasurement.mReceivedGpsTowUncertaintyInNs = parcel.readLong();
             gpsMeasurement.mCn0InDbHz = parcel.readDouble();
             gpsMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
             gpsMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
@@ -1171,6 +1188,7 @@
         parcel.writeDouble(mTimeOffsetInNs);
         parcel.writeInt(mState);
         parcel.writeLong(mReceivedGpsTowInNs);
+        parcel.writeLong(mReceivedGpsTowUncertaintyInNs);
         parcel.writeDouble(mCn0InDbHz);
         parcel.writeDouble(mPseudorangeRateInMetersPerSec);
         parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
@@ -1216,7 +1234,12 @@
 
         builder.append(String.format(format, "State", getStateString()));
 
-        builder.append(String.format(format, "ReceivedGpsTowInNs", mReceivedGpsTowInNs));
+        builder.append(String.format(
+                formatWithUncertainty,
+                "ReceivedGpsTowInNs",
+                mReceivedGpsTowInNs,
+                "ReceivedGpsTowUncertaintyInNs",
+                mReceivedGpsTowUncertaintyInNs));
 
         builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
 
@@ -1321,6 +1344,7 @@
         setTimeOffsetInNs(Long.MIN_VALUE);
         setState(STATE_UNKNOWN);
         setReceivedGpsTowInNs(Long.MIN_VALUE);
+        setReceivedGpsTowUncertaintyInNs(Long.MAX_VALUE);
         setCn0InDbHz(Double.MIN_VALUE);
         setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
         setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index e4102e90..ef42549 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -3756,7 +3756,8 @@
                     break;
 
                 case MSG_MEDIA_SERVER_DIED:
-                    if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) {
+                    if (!mSystemReady ||
+                            (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
                         Log.e(TAG, "Media server died.");
                         sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
                                 null, 500);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index b5cebe3..a95348f 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -213,6 +213,18 @@
     public static final String KEY_I_FRAME_INTERVAL = "i-frame-interval";
 
     /**
+     * A key describing the temporal layering schema.  This is an optional parameter
+     * that applies only to video encoders.  Use {@link MediaCodec#getInputFormat}
+     * after {@link MediaCodec#configure configure} to query if the encoder supports
+     * the desired schema. Supported values are {@code webrtc.vp8.1-layer},
+     * {@code webrtc.vp8.2-layer}, {@code webrtc.vp8.3-layer}, and {@code none}.
+     * If the encoder does not support temporal layering, the input format will
+     * not have an entry with this key.
+     * The associated value is a string.
+     */
+    public static final String KEY_TEMPORAL_LAYERING = "ts-schema";
+
+    /**
      * @hide
      */
     public static final String KEY_STRIDE = "stride";
diff --git a/media/java/android/media/browse/IMediaBrowserService.aidl b/media/java/android/media/browse/IMediaBrowserService.aidl
new file mode 100644
index 0000000..177bd1b
--- /dev/null
+++ b/media/java/android/media/browse/IMediaBrowserService.aidl
@@ -0,0 +1,22 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+
+package android.media.browse;
+
+import android.content.res.Configuration;
+import android.media.browse.IMediaBrowserServiceCallbacks;
+import android.net.Uri;
+import android.os.Bundle;
+
+/**
+ * Media API allows clients to browse through hierarchy of a user’s media collection,
+ * playback a specific media entry and interact with the now playing queue.
+ * @hide
+ */
+oneway interface IMediaBrowserService {
+    void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
+    void disconnect(IMediaBrowserServiceCallbacks callbacks);
+
+    void addSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks);
+    void removeSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks);
+    void loadThumbnail(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/media/browse/IMediaBrowserServiceCallbacks.aidl
new file mode 100644
index 0000000..1f03a1a
--- /dev/null
+++ b/media/java/android/media/browse/IMediaBrowserServiceCallbacks.aidl
@@ -0,0 +1,28 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+
+package android.media.browse;
+
+import android.content.pm.ParceledListSlice;
+import android.graphics.Bitmap;
+import android.media.session.MediaSession;
+import android.net.Uri;
+import android.os.Bundle;
+
+/**
+ * Media API allows clients to browse through hierarchy of a user’s media collection,
+ * playback a specific media entry and interact with the now playing queue.
+ * @hide
+ */
+oneway interface IMediaBrowserServiceCallbacks {
+    /**
+     * Invoked when the connected has been established.
+     * @param root The root Uri for browsing.
+     * @param session The {@link MediaSession.Token media session token} that can be used to control
+     *         the playback of the media app.
+     * @param extra Extras returned by the media service.
+     */
+    void onConnect(in Uri root, in MediaSession.Token session, in Bundle extras);
+    void onConnectFailed();
+    void onLoadChildren(in Uri uri, in ParceledListSlice list);
+    void onLoadThumbnail(in Uri uri, int width, int height, in Bitmap bitmap);
+}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
new file mode 100644
index 0000000..d17f95d
--- /dev/null
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -0,0 +1,842 @@
+/*
+ * 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.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+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.session.MediaSession;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+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.Set;
+
+/**
+ * Browses media content offered by a link MediaBrowserService.
+ * <p>
+ * This object is not thread-safe. All calls should happen on the thread on which the browser
+ * was constructed.
+ * </p>
+ */
+public final class MediaBrowser {
+    private static final String TAG = "MediaBrowser";
+    private static final boolean DBG = false;
+
+    private static final int CONNECT_STATE_DISCONNECTED = 0;
+    private static final int CONNECT_STATE_CONNECTING = 1;
+    private static final int CONNECT_STATE_CONNECTED = 2;
+    private static final int CONNECT_STATE_SUSPENDED = 3;
+
+    private final Context mContext;
+    private final ComponentName mServiceComponent;
+    private final ConnectionCallback mCallback;
+    private final Bundle mRootHints;
+    private final Handler mHandler = new Handler();
+    private final ArrayMap<Uri,Subscription> mSubscriptions =
+            new ArrayMap<Uri, MediaBrowser.Subscription>();
+    private final ArrayMap<ThumbnailRequest, HashSet<ThumbnailCallback>> mThumbnailCallbacks =
+            new ArrayMap<ThumbnailRequest, HashSet<ThumbnailCallback>>();
+
+    private int mState = CONNECT_STATE_DISCONNECTED;
+    private MediaServiceConnection mServiceConnection;
+    private IMediaBrowserService mServiceBinder;
+    private IMediaBrowserServiceCallbacks mServiceCallbacks;
+    private Uri mRootUri;
+    private MediaSession.Token mMediaSessionToken;
+    private Bundle mExtras;
+
+    /**
+     * Creates a media browser for the specified media browse service.
+     *
+     * @param context The context.
+     * @param serviceComponent The component name of the media browse service.
+     * @param callback The connection callback.
+     * @param rootHints An optional bundle of service-specific arguments to send
+     * to the media browse service when connecting and retrieving the root uri
+     * for browsing, or null if none.  The contents of this bundle may affect
+     * the information returned when browsing.
+     */
+    public MediaBrowser(Context context, ComponentName serviceComponent,
+            ConnectionCallback callback, Bundle rootHints) {
+        if (context == null) {
+            throw new IllegalArgumentException("context must not be null");
+        }
+        if (serviceComponent == null) {
+            throw new IllegalArgumentException("service component must not be null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("connection callback must not be null");
+        }
+        mContext = context;
+        mServiceComponent = serviceComponent;
+        mCallback = callback;
+        mRootHints = rootHints;
+    }
+
+    /**
+     * Connects to the media browse service.
+     * <p>
+     * The connection callback specified in the constructor will be invoked
+     * when the connection completes or fails.
+     * </p>
+     */
+    public void connect() {
+        if (mState != CONNECT_STATE_DISCONNECTED) {
+            throw new IllegalStateException("connect() called while not disconnected (state="
+                    + getStateLabel(mState) + ")");
+        }
+        // TODO: remove this extra check.
+        if (DBG) {
+            if (mServiceConnection != null) {
+                throw new RuntimeException("mServiceConnection should be null. Instead it is "
+                        + mServiceConnection);
+            }
+        }
+        if (mServiceBinder != null) {
+            throw new RuntimeException("mServiceBinder should be null. Instead it is "
+                    + mServiceBinder);
+        }
+        if (mServiceCallbacks != null) {
+            throw new RuntimeException("mServiceCallbacks should be null. Instead it is "
+                    + mServiceCallbacks);
+        }
+
+        mState = CONNECT_STATE_CONNECTING;
+
+        final Intent intent = new Intent(MediaBrowserService.SERVICE_ACTION);
+        intent.setComponent(mServiceComponent);
+
+        final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
+
+        try {
+            mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
+        } catch (Exception ex) {
+            Log.e(TAG, "Failed binding to service " + mServiceComponent);
+
+            // Tell them that it didn't work.  We are already on the main thread,
+            // but we don't want to do callbacks inside of connect().  So post it,
+            // and then check that we are on the same ServiceConnection.  We know
+            // we won't also get an onServiceConnected or onServiceDisconnected,
+            // so we won't be doing double callbacks.
+            mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        // Ensure that nobody else came in or tried to connect again.
+                        if (thisConnection == mServiceConnection) {
+                            forceCloseConnection();
+                            mCallback.onConnectionFailed();
+                        }
+                    }
+                });
+        }
+
+        if (DBG) {
+            Log.d(TAG, "connect...");
+            dump();
+        }
+    }
+
+    /**
+     * Disconnects from the media browse service.
+     * After this, no more callbacks will be received.
+     */
+    public void disconnect() {
+        // It's ok to call this any state, because allowing this lets apps not have
+        // to check isConnected() unnecessarily.  They won't appreciate the extra
+        // assertions for this.  We do everything we can here to go back to a sane state.
+        if (mServiceCallbacks != null) {
+            try {
+                mServiceBinder.disconnect(mServiceCallbacks);
+            } catch (RemoteException ex) {
+                // We are disconnecting anyway.  Log, just for posterity but it's not
+                // a big problem.
+                Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
+            }
+        }
+        forceCloseConnection();
+
+        if (DBG) {
+            Log.d(TAG, "disconnect...");
+            dump();
+        }
+    }
+
+    /**
+     * Null out the variables and unbind from the service.  This doesn't include
+     * calling disconnect on the service, because we only try to do that in the
+     * clean shutdown cases.
+     * <p>
+     * Everywhere that calls this EXCEPT for disconnect() should follow it with
+     * a call to mCallback.onConnectionFailed().  Disconnect doesn't do that callback
+     * for a clean shutdown, but everywhere else is a dirty shutdown and should
+     * notify the app.
+     */
+    private void forceCloseConnection() {
+        if (mServiceConnection != null) {
+            mContext.unbindService(mServiceConnection);
+        }
+        mState = CONNECT_STATE_DISCONNECTED;
+        mServiceConnection = null;
+        mServiceBinder = null;
+        mServiceCallbacks = null;
+        mRootUri = null;
+        mMediaSessionToken = null;
+    }
+
+    /**
+     * Returns whether the browser is connected to the service.
+     */
+    public boolean isConnected() {
+        return mState == CONNECT_STATE_CONNECTED;
+    }
+
+    /**
+     * Gets the root Uri.
+     * <p>
+     * Note that the root uri may become invalid or change when when the
+     * browser is disconnected.
+     * </p>
+     *
+     * @throws IllegalStateException if not connected.
+     */
+    public @NonNull Uri getRoot() {
+        if (mState != CONNECT_STATE_CONNECTED) {
+            throw new IllegalStateException("getSessionToken() called while not connected (state="
+                    + getStateLabel(mState) + ")");
+        }
+        return mRootUri;
+    }
+
+    /**
+     * Gets any extras for the media service.
+     *
+     * @throws IllegalStateException if not connected.
+     */
+    public @Nullable Bundle getExtras() {
+        if (mState != CONNECT_STATE_CONNECTED) {
+            throw new IllegalStateException("getExtras() called while not connected (state="
+                    + getStateLabel(mState) + ")");
+        }
+        return mExtras;
+    }
+
+    /**
+     * Gets the media session token associated with the media browser.
+     * <p>
+     * Note that the session token may become invalid or change when when the
+     * browser is disconnected.
+     * </p>
+     *
+     * @return The session token for the browser, never null.
+     *
+     * @throws IllegalStateException if not connected.
+     */
+     public @NonNull MediaSession.Token getSessionToken() {
+        if (mState != CONNECT_STATE_CONNECTED) {
+            throw new IllegalStateException("getSessionToken() called while not connected (state="
+                    + mState + ")");
+        }
+        return mMediaSessionToken;
+    }
+
+    /**
+     * Queries for information about the media items that are contained within
+     * the specified Uri and subscribes to receive updates when they change.
+     * <p>
+     * The list of subscriptions is maintained even when not connected and is
+     * restored after reconnection.  It is ok to subscribe while not connected
+     * but the results will not be returned until the connection completes.
+     * </p><p>
+     * If the uri is already subscribed with a different callback then the new
+     * callback will replace the previous one.
+     * </p>
+     *
+     * @param parentUri The uri of the parent media item whose list of children
+     * will be subscribed.
+     * @param callback The callback to receive the list of children.
+     */
+    public void subscribe(@NonNull Uri parentUri, @NonNull SubscriptionCallback callback) {
+        // Check arguments.
+        if (parentUri == null) {
+            throw new IllegalArgumentException("parentUri is null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("callback is null");
+        }
+
+        // Update or create the subscription.
+        Subscription sub = mSubscriptions.get(parentUri);
+        boolean newSubscription = sub == null;
+        if (newSubscription) {
+            sub = new Subscription(parentUri);
+            mSubscriptions.put(parentUri, sub);
+        }
+        sub.callback = callback;
+
+        // If we are connected, tell the service that we are watching.  If we aren't
+        // connected, the service will be told when we connect.
+        if (mState == CONNECT_STATE_CONNECTED && newSubscription) {
+            try {
+                mServiceBinder.addSubscription(parentUri, mServiceCallbacks);
+            } catch (RemoteException ex) {
+                // Process is crashing.  We will disconnect, and upon reconnect we will
+                // automatically reregister. So nothing to do here.
+                Log.d(TAG, "addSubscription failed with RemoteException parentUri=" + parentUri);
+            }
+        }
+    }
+
+    /**
+     * Unsubscribes for changes to the children of the specified Uri.
+     * <p>
+     * The query callback will no longer be invoked for results associated with
+     * this Uri once this method returns.
+     * </p>
+     *
+     * @param parentUri The uri of the parent media item whose list of children
+     * will be unsubscribed.
+     */
+    public void unsubscribe(@NonNull Uri parentUri) {
+        // Check arguments.
+        if (parentUri == null) {
+            throw new IllegalArgumentException("parentUri is null");
+        }
+
+        // Remove from our list.
+        final Subscription sub = mSubscriptions.remove(parentUri);
+
+        // Tell the service if necessary.
+        if (mState == CONNECT_STATE_CONNECTED && sub != null) {
+            try {
+                mServiceBinder.removeSubscription(parentUri, mServiceCallbacks);
+            } catch (RemoteException ex) {
+                // Process is crashing.  We will disconnect, and upon reconnect we will
+                // automatically reregister. So nothing to do here.
+                Log.d(TAG, "removeSubscription failed with RemoteException parentUri=" + parentUri);
+            }
+        }
+    }
+
+    /**
+     * Loads the thumbnail of a media item.
+     *
+     * @param uri The uri of the thumbnail.
+     * @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 thumbnail.
+     */
+    public void loadThumbnail(final @NonNull Uri uri, final int width, final int height,
+            final @NonNull ThumbnailCallback callback) {
+        if (uri == null) {
+            throw new IllegalArgumentException("thumbnail uri cannot be null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("thumbnail callback cannot be null");
+        }
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                HashSet<ThumbnailCallback> callbackSet;
+                ThumbnailRequest request = new ThumbnailRequest(uri, width, height);
+                callbackSet = mThumbnailCallbacks.get(request);
+                if (callbackSet != null) {
+                    callbackSet.add(callback);
+                    mThumbnailCallbacks.put(request, callbackSet);
+                    // same request has been sent. we will wait for the callback.
+                    return;
+                }
+                callbackSet = new HashSet<ThumbnailCallback>();
+                callbackSet.add(callback);
+                mThumbnailCallbacks.put(request, callbackSet);
+                if (mState == CONNECT_STATE_CONNECTED) {
+                    try {
+                        mServiceBinder.loadThumbnail(uri, width, height, mServiceCallbacks);
+                    } catch (RemoteException e) {
+                        // Process is crashing.  We will disconnect, and upon reconnect we will
+                        // automatically reload the thumbnails. So nothing to do here.
+                        Log.d(TAG, "loadThumbnail failed with RemoteException uri=" + uri);
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * For debugging.
+     */
+    private static String getStateLabel(int state) {
+        switch (state) {
+            case CONNECT_STATE_DISCONNECTED:
+                return "CONNECT_STATE_DISCONNECTED";
+            case CONNECT_STATE_CONNECTING:
+                return "CONNECT_STATE_CONNECTING";
+            case CONNECT_STATE_CONNECTED:
+                return "CONNECT_STATE_CONNECTED";
+            case CONNECT_STATE_SUSPENDED:
+                return "CONNECT_STATE_SUSPENDED";
+            default:
+                return "UNKNOWN/" + state;
+        }
+    }
+
+    private final void onServiceConnected(final IMediaBrowserServiceCallbacks callback,
+            final Uri root, final MediaSession.Token session, final Bundle extra) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                // Check to make sure there hasn't been a disconnect or a different
+                // ServiceConnection.
+                if (!isCurrent(callback, "onConnect")) {
+                    return;
+                }
+                // Don't allow them to call us twice.
+                if (mState != CONNECT_STATE_CONNECTING) {
+                    Log.w(TAG, "onConnect from service while mState="
+                            + getStateLabel(mState) + "... ignoring");
+                    return;
+                }
+                mRootUri = root;
+                mMediaSessionToken = session;
+                mExtras = extra;
+                mState = CONNECT_STATE_CONNECTED;
+
+                if (DBG) {
+                    Log.d(TAG, "ServiceCallbacks.onConnect...");
+                    dump();
+                }
+                mCallback.onConnected();
+
+                // we may receive some subscriptions before we are connected, so re-subscribe
+                // everything now
+                for (Uri uri : mSubscriptions.keySet()) {
+                    try {
+                        mServiceBinder.addSubscription(uri, mServiceCallbacks);
+                    } catch (RemoteException ex) {
+                        // Process is crashing.  We will disconnect, and upon reconnect we will
+                        // automatically reregister. So nothing to do here.
+                        Log.d(TAG, "addSubscription failed with RemoteException parentUri=" + uri);
+                    }
+                }
+
+                for (ThumbnailRequest request : mThumbnailCallbacks.keySet()) {
+                    try {
+                        mServiceBinder.loadThumbnail(request.uri, request.width, request.height,
+                                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, "loadThumbnail failed with RemoteException uri=" + request.uri);
+                    }
+                }
+
+            }
+        });
+    }
+
+    private final void onConnectionFailed(final IMediaBrowserServiceCallbacks callback) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                Log.e(TAG, "onConnectFailed for " + mServiceComponent);
+
+                // Check to make sure there hasn't been a disconnect or a different
+                // ServiceConnection.
+                if (!isCurrent(callback, "onConnectFailed")) {
+                    return;
+                }
+                // Don't allow them to call us twice.
+                if (mState != CONNECT_STATE_CONNECTING) {
+                    Log.w(TAG, "onConnect from service while mState="
+                            + getStateLabel(mState) + "... ignoring");
+                    return;
+                }
+
+                // Clean up
+                forceCloseConnection();
+
+                // Tell the app.
+                mCallback.onConnectionFailed();
+            }
+        });
+    }
+
+    private final void onLoadChildren(final IMediaBrowserServiceCallbacks callback, final Uri uri,
+            final ParceledListSlice list) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                // Check that there hasn't been a disconnect or a different
+                // ServiceConnection.
+                if (!isCurrent(callback, "onLoadChildren")) {
+                    return;
+                }
+
+                List<MediaBrowserItem> data = list.getList();
+                if (DBG) {
+                    Log.d(TAG, "onLoadChildren for " + mServiceComponent + " uri=" + uri);
+                }
+                if (data == null) {
+                    data = Collections.emptyList();
+                }
+
+                // Check that the subscription is still subscribed.
+                final Subscription subscription = mSubscriptions.get(uri);
+                if (subscription == null) {
+                    if (DBG) {
+                        Log.d(TAG, "onLoadChildren for uri that isn't subscribed uri="
+                                + uri);
+                    }
+                    return;
+                }
+
+                // Tell the app.
+                subscription.callback.onChildrenLoaded(uri, data);
+            }
+        });
+    }
+
+    private final void onLoadThumbnail(final IMediaBrowserServiceCallbacks callback,
+            final ThumbnailRequest request, 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, "onLoadThumbnail")) {
+                    return;
+                }
+
+                Set<ThumbnailCallback> callbackSet = mThumbnailCallbacks.get(request);
+                if (callbackSet == null) {
+                    Log.d(TAG, "onLoadThumbnail called for request=" + request +
+                            " but the callback is not registered");
+                    return;
+                }
+                for (ThumbnailCallback thumbnailCallback : callbackSet) {
+                    thumbnailCallback.onThumbnailLoaded(request.uri, bitmap);
+                }
+                mThumbnailCallbacks.remove(request);
+            }
+        });
+    }
+
+
+    /**
+     * Return true if {@code callback} is the current ServiceCallbacks.  Also logs if it's not.
+     */
+    private boolean isCurrent(IMediaBrowserServiceCallbacks callback, String funcName) {
+        if (mServiceCallbacks != callback) {
+            if (mState != CONNECT_STATE_DISCONNECTED) {
+                Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
+                        + mServiceCallbacks + " this=" + this);
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private ServiceCallbacks getNewServiceCallbacks() {
+        return new ServiceCallbacks(this);
+    }
+
+    /**
+     * Log internal state.
+     * @hide
+     */
+    void dump() {
+        Log.d(TAG, "MediaBrowser...");
+        Log.d(TAG, "  mServiceComponent=" + mServiceComponent);
+        Log.d(TAG, "  mCallback=" + mCallback);
+        Log.d(TAG, "  mRootHints=" + mRootHints);
+        Log.d(TAG, "  mState=" + getStateLabel(mState));
+        Log.d(TAG, "  mServiceConnection=" + mServiceConnection);
+        Log.d(TAG, "  mServiceBinder=" + mServiceBinder);
+        Log.d(TAG, "  mServiceCallbacks=" + mServiceCallbacks);
+        Log.d(TAG, "  mRootUri=" + mRootUri);
+        Log.d(TAG, "  mMediaSessionToken=" + mMediaSessionToken);
+    }
+
+
+    /**
+     * Callbacks for connection related events.
+     */
+    public static class ConnectionCallback {
+        /**
+         * Invoked after {@link MediaBrowser#connect()} when the request has successfully completed.
+         */
+        public void onConnected() {
+        }
+
+        /**
+         * Invoked when the client is disconnected from the media browser.
+         */
+        public void onConnectionSuspended() {
+        }
+
+        /**
+         * Invoked when the connection to the media browser failed.
+         */
+        public void onConnectionFailed() {
+        }
+    }
+
+    /**
+     * Callbacks for subscription related events.
+     */
+    public static abstract class SubscriptionCallback {
+        /**
+         * Called when the list of children is loaded or updated.
+         */
+        public void onChildrenLoaded(@NonNull Uri parentUri,
+                                     @NonNull List<MediaBrowserItem> children) {
+        }
+
+        /**
+         * Called when the Uri doesn't exist or other errors in subscribing.
+         * <p>
+         * If this is called, the subscription remains until {@link MediaBrowser#unsubscribe}
+         * called, because some errors may heal themselves.
+         * </p>
+         */
+        public void onError(@NonNull Uri uri) {
+        }
+    }
+
+    /**
+     * Callbacks for thumbnail loading.
+     */
+    public static abstract class ThumbnailCallback {
+        /**
+         * Called when the thumbnail is loaded.
+         */
+        public void onThumbnailLoaded(@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 ThumbnailRequest {
+        Uri uri;
+        int width;
+        int height;
+        ThumbnailRequest(@NonNull Uri uri, int width, int height) {
+            if (uri == null) {
+                throw new IllegalArgumentException("thumbnail uri cannot be null");
+            }
+            this.uri = uri;
+            this.width = width;
+            this.height = height;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof ThumbnailRequest)) return false;
+
+            ThumbnailRequest that = (ThumbnailRequest) o;
+
+            if (height != that.height) return false;
+            if (width != that.width) return false;
+            if (!uri.equals(that.uri)) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = uri.hashCode();
+            result = 31 * result + width;
+            result = 31 * result + height;
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            return "ThumbnailRequest{" +
+                    "uri=" + uri +
+                    ", width=" + width +
+                    ", height=" + height +
+                    '}';
+        }
+    }
+
+    /**
+     * ServiceConnection to the other app.
+     */
+    private class MediaServiceConnection implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder binder) {
+            if (DBG) {
+                Log.d(TAG, "MediaServiceConnection.onServiceConnected name=" + name
+                        + " binder=" + binder);
+                dump();
+            }
+
+            // Make sure we are still the current connection, and that they haven't called
+            // disconnect().
+            if (!isCurrent("onServiceConnected")) {
+                return;
+            }
+
+            // Save their binder
+            mServiceBinder = IMediaBrowserService.Stub.asInterface(binder);
+
+            // We make a new mServiceCallbacks each time we connect so that we can drop
+            // responses from previous connections.
+            mServiceCallbacks = getNewServiceCallbacks();
+
+            // Call connect, which is async. When we get a response from that we will
+            // say that we're connected.
+            try {
+                if (DBG) {
+                    Log.d(TAG, "ServiceCallbacks.onConnect...");
+                    dump();
+                }
+                mServiceBinder.connect(mContext.getPackageName(), mRootHints, mServiceCallbacks);
+            } catch (RemoteException ex) {
+                // Connect failed, which isn't good. But the auto-reconnect on the service
+                // will take over and we will come back.  We will also get the
+                // onServiceDisconnected, which has all the cleanup code.  So let that do it.
+                Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
+                if (DBG) {
+                    Log.d(TAG, "ServiceCallbacks.onConnect...");
+                    dump();
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DBG) {
+                Log.d(TAG, "MediaServiceConnection.onServiceDisconnected name=" + name
+                        + " this=" + this + " mServiceConnection=" + mServiceConnection);
+                dump();
+            }
+
+            // Make sure we are still the current connection, and that they haven't called
+            // disconnect().
+            if (!isCurrent("onServiceDisconnected")) {
+                return;
+            }
+
+            // Clear out what we set in onServiceConnected
+            mServiceBinder = null;
+            mServiceCallbacks = null;
+
+            // And tell the app that it's suspended.
+            mState = CONNECT_STATE_SUSPENDED;
+            mCallback.onConnectionSuspended();
+        }
+
+        /**
+         * Return true if this is the current ServiceConnection.  Also logs if it's not.
+         */
+        private boolean isCurrent(String funcName) {
+            if (mServiceConnection != this) {
+                if (mState != CONNECT_STATE_DISCONNECTED) {
+                    // Check mState, because otherwise this log is noisy.
+                    Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
+                            + mServiceConnection + " this=" + this);
+                }
+                return false;
+            }
+            return true;
+        }
+    };
+
+    /**
+     * Callbacks from the service.
+     */
+    private static class ServiceCallbacks extends IMediaBrowserServiceCallbacks.Stub {
+        private WeakReference<MediaBrowser> mMediaBrowser;
+
+        public ServiceCallbacks(MediaBrowser mediaBrowser) {
+            mMediaBrowser = new WeakReference<MediaBrowser>(mediaBrowser);
+        }
+
+        /**
+         * The other side has acknowledged our connection.  The parameters to this function
+         * are the initial data as requested.
+         */
+        @Override
+        public void onConnect(final Uri root, final MediaSession.Token session,
+                final Bundle extras) {
+            MediaBrowser mediaBrowser = mMediaBrowser.get();
+            if (mediaBrowser != null) {
+                mediaBrowser.onServiceConnected(this, root, session, extras);
+            }
+        }
+
+        /**
+         * The other side does not like us.  Tell the app via onConnectionFailed.
+         */
+        @Override
+        public void onConnectFailed() {
+            MediaBrowser mediaBrowser = mMediaBrowser.get();
+            if (mediaBrowser != null) {
+                mediaBrowser.onConnectionFailed(this);
+            }
+        }
+
+        @Override
+        public void onLoadChildren(final Uri uri, final ParceledListSlice list) {
+            MediaBrowser mediaBrowser = mMediaBrowser.get();
+            if (mediaBrowser != null) {
+                mediaBrowser.onLoadChildren(this, uri, list);
+            }
+        }
+
+        @Override
+        public void onLoadThumbnail(final Uri uri, int width, int height, final Bitmap bitmap) {
+            MediaBrowser mediaBrowser = mMediaBrowser.get();
+            if (mediaBrowser != null) {
+                ThumbnailRequest request = new ThumbnailRequest(uri, width, height);
+                mediaBrowser.onLoadThumbnail(this, request, bitmap);
+            }
+        }
+    }
+
+    private static class Subscription {
+        final Uri uri;
+        SubscriptionCallback callback;
+
+        Subscription(Uri u) {
+            this.uri = u;
+        }
+    }
+}
diff --git a/media/java/android/media/browse/MediaBrowserItem.java b/media/java/android/media/browse/MediaBrowserItem.java
new file mode 100644
index 0000000..38e765f
--- /dev/null
+++ b/media/java/android/media/browse/MediaBrowserItem.java
@@ -0,0 +1,286 @@
+/*
+ * 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.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 Uri mIconUri;
+    private final int mIconResId;
+    private final int mFlags;
+    private final CharSequence mTitle;
+    private final CharSequence mSummary;
+    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, @Nullable Uri iconUri, int iconResId, int flags,
+            @NonNull CharSequence title, CharSequence summary, 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;
+        mIconUri = iconUri;
+        mIconResId = iconResId;
+        mFlags = flags;
+        mTitle = title;
+        mSummary = summary;
+        mExtras = extras;
+    }
+
+    /**
+     * Private constructor.
+     */
+    private MediaBrowserItem(Parcel in) {
+        mUri = Uri.CREATOR.createFromParcel(in);
+        mIconUri = Uri.CREATOR.createFromParcel(in);
+        mIconResId = in.readInt();
+        mFlags = in.readInt();
+        mTitle = in.readCharSequence();
+        if (in.readInt() != 0) {
+            mSummary = in.readCharSequence();
+        } else {
+            mSummary = null;
+        }
+        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);
+        mIconUri.writeToParcel(out, flags);
+        out.writeInt(mIconResId);
+        out.writeInt(mFlags);
+        out.writeCharSequence(mTitle);
+        if (mSummary != null) {
+            out.writeInt(1);
+            out.writeCharSequence(mSummary);
+        } else {
+            out.writeInt(0);
+        }
+        if (mExtras != null) {
+            out.writeInt(1);
+            mExtras.writeToParcel(out, flags);
+        } else {
+            out.writeInt(0);
+        }
+    }
+
+    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 Uri of the icon.
+     */
+    public @Nullable Uri getIconUri() {
+        return mIconUri;
+    }
+
+    /**
+     * Gets the resource id of the icon.
+     */
+    public int getIconResId() {
+        return mIconResId;
+    }
+
+    /**
+     * 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 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 Uri mIconUri;
+        private int mIconResId;
+        private CharSequence mSummary;
+        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 the uri of the icon.
+         * <p>
+         * If both {@link #setIconUri(Uri)} and {@link #setIconResId(int)} are called,
+         * 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.
+         */
+        public @NonNull Builder setIconResId(int resId) {
+            mIconResId = resId;
+            return this;
+        }
+
+        /**
+         * Sets summary of the item, or null if none.
+         */
+        public @NonNull Builder setSummary(@Nullable CharSequence summary) {
+            mSummary = summary;
+            return this;
+        }
+
+        /**
+        * Sets additional service-specified extras about the
+        * item or its content, or null if none.
+        */
+        public @NonNull Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+        * Builds the item.
+        */
+        public @NonNull MediaBrowserItem build() {
+            return new MediaBrowserItem(mUri, mIconUri, mIconResId,
+                    mFlags, mTitle, mSummary, mExtras);
+        }
+    }
+}
+
diff --git a/media/java/android/media/browse/MediaBrowserService.java b/media/java/android/media/browse/MediaBrowserService.java
new file mode 100644
index 0000000..57befe7
--- /dev/null
+++ b/media/java/android/media/browse/MediaBrowserService.java
@@ -0,0 +1,403 @@
+/*
+ * 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.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.media.session.MediaSession;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Base class for media browse services.
+ * <p>
+ * Media browse services enable applications to browse media content provided by an application
+ * and ask the application to start playing it.  They may also be used to control content that
+ * is already playing by way of a {@link MediaSession}.
+ * </p>
+ *
+ * To extend this class, you must declare the service in your manifest file with
+ * an intent filter with the {@link #SERVICE_ACTION} action.
+ *
+ * For example:
+ * </p><pre>
+ * &lt;service android:name=".MyMediaBrowserService"
+ *          android:label="&#64;string/service_name" >
+ *     &lt;intent-filter>
+ *         &lt;action android:name="android.media.browse.MediaBrowserService" />
+ *     &lt;/intent-filter>
+ * &lt;/service>
+ * </pre>
+ *
+ */
+public abstract class MediaBrowserService extends Service {
+    private static final String TAG = "MediaBrowserService";
+
+    private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
+    private final Handler mHandler = new Handler();
+    private ServiceBinder mBinder;
+    MediaSession.Token mSession;
+
+    /**
+     * All the info about a connection.
+     */
+    private class ConnectionRecord {
+        String pkg;
+        Bundle rootHints;
+        IMediaBrowserServiceCallbacks callbacks;
+        BrowserRoot root;
+        HashSet<Uri> subscriptions = new HashSet();
+    }
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+
+    private class ServiceBinder extends IMediaBrowserService.Stub {
+        @Override
+        public void connect(final String pkg, final Bundle rootHints,
+                final IMediaBrowserServiceCallbacks callbacks) {
+
+            final int uid = Binder.getCallingUid();
+            if (!isValidPackage(pkg, uid)) {
+                throw new IllegalArgumentException("Package/uid mismatch: uid=" + uid
+                        + " package=" + pkg);
+            }
+
+            mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        final IBinder b = callbacks.asBinder();
+
+                        // Clear out the old subscriptions.  We are getting new ones.
+                        mConnections.remove(b);
+
+                        final ConnectionRecord connection = new ConnectionRecord();
+                        connection.pkg = pkg;
+                        connection.rootHints = rootHints;
+                        connection.callbacks = callbacks;
+
+                        connection.root = MediaBrowserService.this.onGetRoot(pkg, uid, rootHints);
+
+                        // If they didn't return something, don't allow this client.
+                        if (connection.root == null) {
+                            Log.i(TAG, "No root for client " + pkg + " from service "
+                                    + getClass().getName());
+                            try {
+                                callbacks.onConnectFailed();
+                            } catch (RemoteException ex) {
+                                Log.w(TAG, "Calling onConnectFailed() failed. Ignoring. "
+                                        + "pkg=" + pkg);
+                            }
+                        } else {
+                            try {
+                                mConnections.put(b, connection);
+                                callbacks.onConnect(connection.root.getRootUri(),
+                                        mSession, connection.root.getExtras());
+                            } catch (RemoteException ex) {
+                                Log.w(TAG, "Calling onConnect() failed. Dropping client. "
+                                        + "pkg=" + pkg);
+                                mConnections.remove(b);
+                            }
+                        }
+                    }
+                });
+        }
+
+        @Override
+        public void disconnect(final IMediaBrowserServiceCallbacks callbacks) {
+            mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        final IBinder b = callbacks.asBinder();
+
+                        // Clear out the old subscriptions.  We are getting new ones.
+                        final ConnectionRecord old = mConnections.remove(b);
+                        if (old != null) {
+                            // TODO
+                        }
+                    }
+                });
+        }
+
+
+        @Override
+        public void addSubscription(final Uri uri, final IMediaBrowserServiceCallbacks callbacks) {
+            mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        final IBinder b = callbacks.asBinder();
+
+                        // Get the record for the connection
+                        final ConnectionRecord connection = mConnections.get(b);
+                        if (connection == null) {
+                            Log.w(TAG, "addSubscription for callback that isn't registered uri="
+                                + uri);
+                            return;
+                        }
+
+                        MediaBrowserService.this.addSubscription(uri, connection);
+                    }
+                });
+        }
+
+        @Override
+        public void removeSubscription(final Uri uri,
+                final IMediaBrowserServiceCallbacks callbacks) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    final IBinder b = callbacks.asBinder();
+
+                    ConnectionRecord connection = mConnections.get(b);
+                    if (connection == null) {
+                        Log.w(TAG, "removeSubscription for callback that isn't registered uri="
+                                + uri);
+                        return;
+                    }
+                    if (!connection.subscriptions.remove(uri)) {
+                        Log.w(TAG, "removeSubscription called for " + uri
+                                + " which is not subscribed");
+                    }
+                }
+            });
+        }
+
+        @Override
+        public void loadThumbnail(final Uri uri, final int width, final int height,
+                final IMediaBrowserServiceCallbacks callbacks) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    Bitmap bitmap = onGetThumbnail(uri, width, height);
+                    try {
+                        callbacks.onLoadThumbnail(uri, width, height, bitmap);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "RemoteException in calling onLoadThumbnail", e);
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mBinder = new ServiceBinder();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (SERVICE_ACTION.equals(intent.getAction())) {
+            return mBinder;
+        }
+        return null;
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+    }
+
+    /**
+     * Called to get the root information for browsing by a particular client.
+     * <p>
+     * The implementation should verify that the client package has
+     * permission to access browse media information before returning
+     * the root uri; it should return null if the client is not
+     * allowed to access this information.
+     * </p>
+     *
+     * @param clientPackageName The package name of the application
+     * which is requesting access to browse media.
+     * @param clientUid The uid of the application which is requesting
+     * access to browse media.
+     * @param rootHints An optional bundle of service-specific arguments to send
+     * to the media browse service when connecting and retrieving the root uri
+     * for browsing, or null if none.  The contents of this bundle may affect
+     * the information returned when browsing.
+     */
+    protected abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
+            int clientUid, @Nullable Bundle rootHints);
+
+    /**
+     * Called to get information about the children of a media item.
+     *
+     * @param parentUri The uri of the parent media item whose
+     * children are to be queried.
+     * @return The list of children, or null if the uri is invalid.
+     */
+    protected abstract @Nullable List<MediaBrowserItem> onLoadChildren(@NonNull Uri parentUri);
+
+    /**
+     * Called to get the thumbnail of a particular media item.
+     *
+     * @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 thumbnail, which may then be loaded
+     *          using a bitmap factory, or null if the item does not have a thumbnail.
+     */
+    protected abstract @Nullable Bitmap onGetThumbnail(@NonNull Uri uri, int width, int height);
+
+    /**
+     * Call to set the media session.
+     * <p>
+     * This must be called before onCreate returns.
+     *
+     * @return The media session token, must not be null.
+     */
+    public void setSessionToken(MediaSession.Token token) {
+        if (token == null) {
+            throw new IllegalStateException(this.getClass().getName()
+                    + ".onCreateSession() set invalid MediaSession.Token");
+        }
+        mSession = token;
+    }
+
+    /**
+     * Gets the session token, or null if it has not yet been created
+     * or if it has been destroyed.
+     */
+    public @Nullable MediaSession.Token getSessionToken() {
+        return mSession;
+    }
+
+    /**
+     * Notifies all connected media browsers that the children of
+     * the specified Uri have changed in some way.
+     * This will cause browsers to fetch subscribed content again.
+     *
+     * @param parentUri The uri of the parent media item whose
+     * children changed.
+     */
+    public void notifyChildrenChanged(@NonNull Uri parentUri) {
+        if (parentUri == null) {
+            throw new IllegalArgumentException("parentUri cannot be null in notifyChildrenChanged");
+        }
+        for (IBinder binder : mConnections.keySet()) {
+            ConnectionRecord connection = mConnections.get(binder);
+            Set<Uri> uris = connection.subscriptions;
+            for (Uri uri : uris) {
+                if (uri.equals(parentUri)) {
+                    performLoadChildren(uri, connection);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Return whether the given package is one of the ones that is owned by the uid.
+     */
+    private boolean isValidPackage(String pkg, int uid) {
+        if (pkg == null) {
+            return false;
+        }
+        final PackageManager pm = getPackageManager();
+        final String[] packages = pm.getPackagesForUid(uid);
+        final int N = packages.length;
+        for (int i=0; i<N; i++) {
+            if (packages[i].equals(pkg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Save the subscription and if it is a new subscription send the results.
+     */
+    private void addSubscription(Uri uri, ConnectionRecord connection) {
+        // Save the subscription
+        final boolean added = connection.subscriptions.add(uri);
+
+        // If this is a new subscription, send the results
+        if (added) {
+            performLoadChildren(uri, connection);
+        }
+    }
+
+    /**
+     * Call onLoadChildren and then send the results back to the connection.
+     * <p>
+     * Callers must make sure that this connection is still connected.
+     * <p>
+     * TODO: Think about caching and combining these calls.
+     */
+    private void performLoadChildren(Uri uri, ConnectionRecord connection) {
+        final List<MediaBrowserItem> list = onLoadChildren(uri);
+        if (list == null) {
+            throw new IllegalStateException("onLoadChildren returned null for uri " + uri);
+        }
+        final ParceledListSlice<MediaBrowserItem> pls = new ParceledListSlice(list);
+        try {
+            connection.callbacks.onLoadChildren(uri, pls);
+        } catch (RemoteException ex) {
+            // The other side is in the process of crashing.
+            Log.w(TAG, "Calling onLoadChildren() failed for uri=" + uri
+                    + " package=" + connection.pkg);
+        }
+    }
+
+    public static class BrowserRoot {
+        final private Uri mUri;
+        final private Bundle mExtras;
+        public BrowserRoot(@NonNull Uri uri, @Nullable Bundle extras) {
+            if (uri == null) {
+                throw new IllegalArgumentException("The root uri in BrowserRoot cannot be null. " +
+                        "Use null for BrowserRoot instead.");
+            }
+            mUri = uri;
+            mExtras = extras;
+        }
+
+        Uri getRootUri() {
+            return mUri;
+        }
+
+        Bundle getExtras() {
+            return mExtras;
+        }
+    }
+}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 78e0404..cd0e776 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -16,6 +16,7 @@
 
 package android.media.tv;
 
+import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -120,6 +121,15 @@
     }
 
     /**
+     * Returns true, if {@code channelUri} is a channel URI for a passthrough TV input.
+     * @hide
+     */
+    @SystemApi
+    public static final boolean isChannelUriForPassthroughTvInput(Uri channelUri) {
+        return channelUri.toString().endsWith(PATH_PASSTHROUGH);
+    }
+
+    /**
      * Builds a URI that points to a channel logo. See {@link Channels.Logo}.
      *
      * @param channelId The ID of the channel whose logo is pointed to.
@@ -340,85 +350,85 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
 
         /** A generic channel type. */
-        public static final int TYPE_OTHER = 0x0;
+        public static final String TYPE_OTHER = "TYPE_OTHER";
 
         /** The channel type for NTSC. */
-        public static final int TYPE_NTSC = 0x1;
+        public static final String TYPE_NTSC = "TYPE_NTSC";
 
         /** The channel type for PAL. */
-        public static final int TYPE_PAL = 0x2;
+        public static final String TYPE_PAL = "TYPE_PAL";
 
         /** The channel type for SECAM. */
-        public static final int TYPE_SECAM = 0x3;
+        public static final String TYPE_SECAM = "TYPE_SECAM";
 
         /** The channel type for DVB-T (terrestrial). */
-        public static final int TYPE_DVB_T = 0x00010000;
+        public static final String TYPE_DVB_T = "TYPE_DVB_T";
 
         /** The channel type for DVB-T2 (terrestrial). */
-        public static final int TYPE_DVB_T2 = 0x00010001;
+        public static final String TYPE_DVB_T2 = "TYPE_DVB_T2";
 
         /** The channel type for DVB-S (satellite). */
-        public static final int TYPE_DVB_S = 0x00010100;
+        public static final String TYPE_DVB_S = "TYPE_DVB_S";
 
         /** The channel type for DVB-S2 (satellite). */
-        public static final int TYPE_DVB_S2 = 0x00010101;
+        public static final String TYPE_DVB_S2 = "TYPE_DVB_S2";
 
         /** The channel type for DVB-C (cable). */
-        public static final int TYPE_DVB_C = 0x00010200;
+        public static final String TYPE_DVB_C = "TYPE_DVB_C";
 
         /** The channel type for DVB-C2 (cable). */
-        public static final int TYPE_DVB_C2 = 0x00010201;
+        public static final String TYPE_DVB_C2 = "TYPE_DVB_C2";
 
         /** The channel type for DVB-H (handheld). */
-        public static final int TYPE_DVB_H = 0x00010300;
+        public static final String TYPE_DVB_H = "TYPE_DVB_H";
 
         /** The channel type for DVB-SH (satellite). */
-        public static final int TYPE_DVB_SH = 0x00010400;
+        public static final String TYPE_DVB_SH = "TYPE_DVB_SH";
 
         /** The channel type for ATSC (terrestrial). */
-        public static final int TYPE_ATSC_T = 0x00020000;
+        public static final String TYPE_ATSC_T = "TYPE_ATSC_T";
 
         /** The channel type for ATSC (cable). */
-        public static final int TYPE_ATSC_C = 0x00020200;
+        public static final String TYPE_ATSC_C = "TYPE_ATSC_C";
 
         /** The channel type for ATSC-M/H (mobile/handheld). */
-        public static final int TYPE_ATSC_M_H = 0x00020300;
+        public static final String TYPE_ATSC_M_H = "TYPE_ATSC_M_H";
 
         /** The channel type for ISDB-T (terrestrial). */
-        public static final int TYPE_ISDB_T = 0x00030000;
+        public static final String TYPE_ISDB_T = "TYPE_ISDB_T";
 
         /** The channel type for ISDB-Tb (Brazil). */
-        public static final int TYPE_ISDB_TB = 0x00030100;
+        public static final String TYPE_ISDB_TB = "TYPE_ISDB_TB";
 
         /** The channel type for ISDB-S (satellite). */
-        public static final int TYPE_ISDB_S = 0x00030200;
+        public static final String TYPE_ISDB_S = "TYPE_ISDB_S";
 
         /** The channel type for ISDB-C (cable). */
-        public static final int TYPE_ISDB_C = 0x00030300;
+        public static final String TYPE_ISDB_C = "TYPE_ISDB_C";
 
         /** The channel type for 1seg (handheld). */
-        public static final int TYPE_1SEG = 0x00030400;
+        public static final String TYPE_1SEG = "TYPE_1SEG";
 
         /** The channel type for DTMB (terrestrial). */
-        public static final int TYPE_DTMB = 0x00040000;
+        public static final String TYPE_DTMB = "TYPE_DTMB";
 
         /** The channel type for CMMB (handheld). */
-        public static final int TYPE_CMMB = 0x00040100;
+        public static final String TYPE_CMMB = "TYPE_CMMB";
 
         /** The channel type for T-DMB (terrestrial). */
-        public static final int TYPE_T_DMB = 0x00050000;
+        public static final String TYPE_T_DMB = "TYPE_T_DMB";
 
         /** The channel type for S-DMB (satellite). */
-        public static final int TYPE_S_DMB = 0x00050100;
+        public static final String TYPE_S_DMB = "TYPE_S_DMB";
 
         /** A generic service type. */
-        public static final int SERVICE_TYPE_OTHER = 0x0;
+        public static final String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER";
 
         /** The service type for regular TV channels that have both audio and video. */
-        public static final int SERVICE_TYPE_AUDIO_VIDEO = 0x1;
+        public static final String SERVICE_TYPE_AUDIO_VIDEO = "SERVICE_TYPE_AUDIO_VIDEO";
 
         /** The service type for radio channels that have audio only. */
-        public static final int SERVICE_TYPE_AUDIO = 0x2;
+        public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
 
         /** The video format for 240p. */
         public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P";
@@ -521,7 +531,7 @@
          * </p><p>
          * This is a required field.
          * </p><p>
-         * Type: INTEGER
+         * Type: TEXT
          * </p>
          */
         public static final String COLUMN_TYPE = "type";
@@ -537,7 +547,7 @@
          * </p><p>
          * This is a required field.
          * </p><p>
-         * Type: INTEGER
+         * Type: TEXT
          * </p>
          */
         public static final String COLUMN_SERVICE_TYPE = "service_type";
@@ -809,12 +819,46 @@
         /**
          * The title of this TV program.
          * <p>
+         * If this program is an episodic TV show, it is recommended that the title is the series
+         * title and its related fields ({@link #COLUMN_SEASON_NUMBER},
+         * {@link #COLUMN_EPISODE_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
+         * </p><p>
          * Type: TEXT
          * </p>
          **/
         public static final String COLUMN_TITLE = "title";
 
         /**
+         * The season number of this TV program for episodic TV shows.
+         * <p>
+         * Can be empty.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         **/
+        public static final String COLUMN_SEASON_NUMBER = "season_number";
+
+        /**
+         * The episode number of this TV program for episodic TV shows.
+         * <p>
+         * Can be empty.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         **/
+        public static final String COLUMN_EPISODE_NUMBER = "episode_number";
+
+        /**
+         * The episode title of this TV program for episodic TV shows.
+         * <p>
+         * Can be empty.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         **/
+        public static final String COLUMN_EPISODE_TITLE = "episode_title";
+
+        /**
          * The start time of this TV program, in milliseconds since the epoch.
          * <p>
          * Type: INTEGER (long)
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 86fd4ff..52c0534 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -16,6 +16,7 @@
 
 package android.media.tv;
 
+import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -28,17 +29,20 @@
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.SparseIntArray;
 import android.util.Xml;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.io.InputStream;
 
 /**
  * This class is used to specify meta information of a TV input.
@@ -47,60 +51,55 @@
     private static final boolean DEBUG = false;
     private static final String TAG = "TvInputInfo";
 
+    // Should be in sync with frameworks/base/core/res/res/values/attrs.xml
     /**
-     * TV input type: the TV input service is not handling input from hardware. For example,
-     * services showing streaming from the internet falls into this type.
+     * TV input type: the TV input service is a tuner which provides channels.
      */
-    public static final int TYPE_VIRTUAL = 0;
-
-    // Should be in sync with TvInputHardwareInfo.
-
+    public static final int TYPE_TUNER = 0;
     /**
      * TV input type: a generic hardware TV input type.
      */
-    public static final int TYPE_OTHER_HARDWARE = TvInputHardwareInfo.TV_INPUT_TYPE_OTHER_HARDWARE;
-    /**
-     * TV input type: the TV input service is a tuner. (e.g. terrestrial tuner)
-     */
-    public static final int TYPE_TUNER = TvInputHardwareInfo.TV_INPUT_TYPE_TUNER;
+    public static final int TYPE_OTHER = 1000;
     /**
      * TV input type: the TV input service represents a composite port.
      */
-    public static final int TYPE_COMPOSITE = TvInputHardwareInfo.TV_INPUT_TYPE_COMPOSITE;
+    public static final int TYPE_COMPOSITE = 1001;
     /**
      * TV input type: the TV input service represents a SVIDEO port.
      */
-    public static final int TYPE_SVIDEO = TvInputHardwareInfo.TV_INPUT_TYPE_SVIDEO;
+    public static final int TYPE_SVIDEO = 1002;
     /**
      * TV input type: the TV input service represents a SCART port.
      */
-    public static final int TYPE_SCART = TvInputHardwareInfo.TV_INPUT_TYPE_SCART;
+    public static final int TYPE_SCART = 1003;
     /**
      * TV input type: the TV input service represents a component port.
      */
-    public static final int TYPE_COMPONENT = TvInputHardwareInfo.TV_INPUT_TYPE_COMPONENT;
+    public static final int TYPE_COMPONENT = 1004;
     /**
      * TV input type: the TV input service represents a VGA port.
      */
-    public static final int TYPE_VGA = TvInputHardwareInfo.TV_INPUT_TYPE_VGA;
+    public static final int TYPE_VGA = 1005;
     /**
      * TV input type: the TV input service represents a DVI port.
      */
-    public static final int TYPE_DVI = TvInputHardwareInfo.TV_INPUT_TYPE_DVI;
+    public static final int TYPE_DVI = 1006;
     /**
      * TV input type: the TV input service is HDMI. (e.g. HDMI 1)
      */
-    public static final int TYPE_HDMI = TvInputHardwareInfo.TV_INPUT_TYPE_HDMI;
+    public static final int TYPE_HDMI = 1007;
     /**
      * TV input type: the TV input service represents a display port.
      */
-    public static final int TYPE_DISPLAY_PORT = TvInputHardwareInfo.TV_INPUT_TYPE_DISPLAY_PORT;
+    public static final int TYPE_DISPLAY_PORT = 1008;
 
     /**
      * The ID of the TV input to provide to the setup activity and settings activity.
      */
     public static final String EXTRA_INPUT_ID = "inputId";
 
+    private static SparseIntArray sHardwareTypeToTvInputType = new SparseIntArray();
+
     private static final String XML_START_TAG_NAME = "tv-input";
 
     private final ResolveInfo mService;
@@ -110,7 +109,24 @@
     // Attributes from XML meta data.
     private String mSetupActivity;
     private String mSettingsActivity;
-    private int mType = TYPE_VIRTUAL;
+    private int mType = TYPE_TUNER;
+    private String mLabel;
+    private Uri mIconUri;
+
+    static {
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_OTHER_HARDWARE,
+                TYPE_OTHER);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_TUNER, TYPE_TUNER);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_COMPOSITE, TYPE_COMPOSITE);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_SVIDEO, TYPE_SVIDEO);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_SCART, TYPE_SCART);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_COMPONENT, TYPE_COMPONENT);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_VGA, TYPE_VGA);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_DVI, TYPE_DVI);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_HDMI, TYPE_HDMI);
+        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_DISPLAY_PORT,
+                TYPE_DISPLAY_PORT);
+    }
 
     /**
      * Create a new instance of the TvInputInfo class,
@@ -123,7 +139,7 @@
             throws XmlPullParserException, IOException {
         return createTvInputInfo(context, service, generateInputIdForComponentName(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name)),
-                null);
+                null, TYPE_TUNER, null, null);
     }
 
     /**
@@ -132,13 +148,21 @@
      *
      * @param service The ResolveInfo returned from the package manager about this TV input service.
      * @param cecInfo The HdmiCecDeviceInfo for a HDMI CEC logical device.
+     * @param parentId The ID of this TV input's parent input. {@code null} if none exists.
+     * @param iconUri The {@link android.net.Uri} to load the icon image.
+     *        {@see android.content.ContentResolver#openInputStream}. If it is null, the application
+     *        icon of {@code service} will be loaded.
+     * @param label The label of this TvInputInfo. If it is null or empty, {@code service} label
+     *        will be loaded.
      * @hide
      */
+    @SystemApi
     public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
-            HdmiCecDeviceInfo cecInfo, String parentId) throws XmlPullParserException, IOException {
+            HdmiCecDeviceInfo cecInfo, String parentId, String label, Uri iconUri)
+                    throws XmlPullParserException, IOException {
         return createTvInputInfo(context, service, generateInputIdForHdmiCec(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
-                cecInfo), parentId);
+                cecInfo), parentId, TYPE_HDMI, label, iconUri);
     }
 
     /**
@@ -147,17 +171,26 @@
      *
      * @param service The ResolveInfo returned from the package manager about this TV input service.
      * @param hardwareInfo The TvInputHardwareInfo for a TV input hardware device.
+     * @param iconUri The {@link android.net.Uri} to load the icon image.
+     *        {@see android.content.ContentResolver#openInputStream}. If it is null, the application
+     *        icon of {@code service} will be loaded.
+     * @param label The label of this TvInputInfo. If it is null or empty, {@code service} label
+     *        will be loaded.
      * @hide
      */
+    @SystemApi
     public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
-            TvInputHardwareInfo hardwareInfo) throws XmlPullParserException, IOException {
+            TvInputHardwareInfo hardwareInfo, String label, Uri iconUri)
+                    throws XmlPullParserException, IOException {
+        int inputType = sHardwareTypeToTvInputType.get(hardwareInfo.getType(), TYPE_TUNER);
         return createTvInputInfo(context, service, generateInputIdForHardware(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
-                hardwareInfo), null);
+                hardwareInfo), null, inputType, label, iconUri);
     }
 
     private static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
-            String id, String parentId) throws XmlPullParserException, IOException {
+            String id, String parentId, int inputType, String label, Uri iconUri)
+                    throws XmlPullParserException, IOException {
         ServiceInfo si = service.serviceInfo;
         PackageManager pm = context.getPackageManager();
         XmlResourceParser parser = null;
@@ -182,7 +215,7 @@
                         "Meta-data does not start with tv-input-service tag in " + si.name);
             }
 
-            TvInputInfo input = new TvInputInfo(service, id, parentId);
+            TvInputInfo input = new TvInputInfo(service, id, parentId, inputType);
             TypedArray sa = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.TvInputService);
             input.mSetupActivity = sa.getString(
@@ -196,16 +229,10 @@
                 Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
                         + si.name);
             }
-            if (pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, si.packageName)
-                    == PackageManager.PERMISSION_GRANTED) {
-                input.mType = sa.getInt(
-                        com.android.internal.R.styleable.TvInputService_tvInputType, TYPE_VIRTUAL);
-                if (DEBUG) {
-                    Log.d(TAG, "Type loaded. [" + input.mType + "] for " + si.name);
-                }
-            }
             sa.recycle();
 
+            input.mLabel = label;
+            input.mIconUri = iconUri;
             return input;
         } catch (NameNotFoundException e) {
             throw new XmlPullParserException("Unable to create context for: " + si.packageName);
@@ -222,11 +249,13 @@
      * @param service The ResolveInfo returned from the package manager about this TV input service.
      * @param id ID of this TV input. Should be generated via generateInputId*().
      * @param parentId ID of this TV input's parent input. {@code null} if none exists.
+     * @param type The type of this TV input service.
      */
-    private TvInputInfo(ResolveInfo service, String id, String parentId) {
+    private TvInputInfo(ResolveInfo service, String id, String parentId, int type) {
         mService = service;
         mId = id;
         mParentId = parentId;
+        mType = type;
     }
 
     /**
@@ -314,12 +343,7 @@
      * @see TvContract#buildChannelUriForPassthroughTvInput(String)
      */
     public boolean isPassthroughInputType() {
-        if (mType == TYPE_HDMI || mType == TYPE_DISPLAY_PORT || mType == TYPE_SCART
-                || mType == TYPE_DVI || mType == TYPE_VGA || mType == TYPE_COMPONENT
-                || mType == TYPE_COMPOSITE || mType == TYPE_SVIDEO) {
-            return true;
-        }
-        return false;
+        return mType != TYPE_TUNER;
     }
 
     /**
@@ -330,7 +354,11 @@
      *         a label, its name is returned.
      */
     public CharSequence loadLabel(Context context) {
-        return mService.loadLabel(context.getPackageManager());
+        if (TextUtils.isEmpty(mLabel)) {
+            return mService.loadLabel(context.getPackageManager());
+        } else {
+            return mLabel;
+        }
     }
 
     /**
@@ -342,7 +370,19 @@
      *         returned.
      */
     public Drawable loadIcon(Context context) {
-        return mService.serviceInfo.loadIcon(context.getPackageManager());
+        if (mIconUri == null) {
+            return loadDefaultIcon(context);
+        }
+        try (InputStream is = context.getContentResolver().openInputStream(mIconUri)) {
+            Drawable drawable = Drawable.createFromStream(is, null);
+            if (drawable == null) {
+                return loadDefaultIcon(context);
+            }
+            return drawable;
+        } catch (IOException e) {
+            Log.w(TAG, "Loading the default icon due to a failure on loading " + mIconUri, e);
+            return loadDefaultIcon(context);
+        }
     }
 
     @Override
@@ -390,6 +430,12 @@
         dest.writeString(mSetupActivity);
         dest.writeString(mSettingsActivity);
         dest.writeInt(mType);
+        dest.writeString(mIconUri == null ? null : mIconUri.toString());
+        dest.writeString(mLabel);
+    }
+
+    private Drawable loadDefaultIcon(Context context) {
+        return mService.serviceInfo.loadIcon(context.getPackageManager());
     }
 
     /**
@@ -451,5 +497,10 @@
         mSetupActivity = in.readString();
         mSettingsActivity = in.readString();
         mType = in.readInt();
+        String mIconUriString = in.readString();
+        if (mIconUriString != null) {
+            mIconUri = Uri.parse(mIconUriString);
+        }
+        mLabel = in.readString();
     }
 }
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index aee5adc..1b84568 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Velikost papíru:"</string>
     <string name="label_color" msgid="1108690305218188969">"Barva"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientace"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Stránky"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Vše: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Rozsah: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"např. 1–5, 8, 11–13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Náhled tisku"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Nainstalovat prohlížeč PDF (umožní náhled)"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 7212319..9b72da1 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Taille du papier :"</string>
     <string name="label_color" msgid="1108690305218188969">"Couleur"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Toutes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Plage de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Aperçu avant impression"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Installer un lecteur PDF pour voir l\'aperçu"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 58f761d..3b82f85 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Veličina papira:"</string>
     <string name="label_color" msgid="1108690305218188969">"U boji"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orijentacija"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Stranice"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Sve stranice (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Raspon od <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"npr. 1 – 5,8,11 – 13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Pregled ispisa"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Instaliraj PDF preglednik za pregled"</string>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index a688d35..f77a7e8 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Թղթի չափը՝"</string>
     <string name="label_color" msgid="1108690305218188969">"Գույնը"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Դիրքավորում"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Էջեր"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Բոլորը՝ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Միջակայքը՝ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"օր.՝ 1-5, 8, 11-13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Տպելու նախադիտում"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Նախադիտման համար տեղադրեք PDF դիտարկիչ"</string>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index a6200fa..d885765 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"ფურცლის ზომა:"</string>
     <string name="label_color" msgid="1108690305218188969">"ფერი"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ორიენტაცია"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"გვერდები"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"ყველა <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>-ის არეალი"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"მაგ. 1–5, 8, 11–13"</string>
     <string name="print_preview" msgid="8010217796057763343">"ნახვა ამობეჭდვამდე"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"გადახედვისთვის დააყენეთ PDF მნახველი"</string>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index 0ab170e..8c6a34fd 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Қағаз өлшемі:"</string>
     <string name="label_color" msgid="1108690305218188969">"Түс"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Бағыты"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Беттер"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Барлық <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ауқымы"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"мысалы, 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Алдын ала көру"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Алдын ала көру мүмкін болу үшін PDF шолушыны орнатыңыз"</string>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index c14b47f..f60f994 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Барактын өлчөмү:"</string>
     <string name="label_color" msgid="1108690305218188969">"Түс"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Багыттоо"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Баракчалар"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Бардыгы <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> аралыгы"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"мис. 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Алдын ала көрүү"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Алдын ала көрүү үчүн PDF-серепчи орнотуңуз"</string>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 5ee274f..f327334 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Saiz kertas:"</string>
     <string name="label_color" msgid="1108690305218188969">"Warna"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Halaman"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Semua <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Julat <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"cth. 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Pratonton cetak"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Pasang pemapar PDF untuk pratonton"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index 3a8a231..6abc571 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Размер бумаги:"</string>
     <string name="label_color" msgid="1108690305218188969">"Печать"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Страницы"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Все <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Диапазон <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"напр., 1–5, 8, 11–13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Предварительный просмотр"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Установить средство просмотра PDF"</string>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 6963050..f6cc5e2 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"කඩදාසියේ ප්‍රමාණය:"</string>
     <string name="label_color" msgid="1108690305218188969">"වර්ණය"</string>
     <string name="label_orientation" msgid="2853142581990496477">"දිශානතිය"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"පිටු"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"සියලුම <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> පරාසය"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"උ.දා. 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"මුද්‍රණ පෙරදසුන"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"පෙරදසුන සඳහා PDF දක්වනය ස්ථාපනය කරන්න"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 47b4f06..439aae4 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Veľkosť papiera:"</string>
     <string name="label_color" msgid="1108690305218188969">"Farba"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientácia"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Strany"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Všetky: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Rozsah: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"napr. 1–5, 8, 11–13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Ukážka pred tlačou"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Inštalovať zobrazovač PDF na zobrazenie ukážky"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 7de3adf..de0dfac 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Величина папира:"</string>
     <string name="label_color" msgid="1108690305218188969">"Боја"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Положај"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Странице"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Све странице (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Опсег од <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"нпр. 1–5, 8, 11–13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Преглед пре штампања"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Инсталирај PDF приказивач за преглед"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index 921bfca..d1d45fe 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"ขนาดของกระดาษ:"</string>
     <string name="label_color" msgid="1108690305218188969">"สี"</string>
     <string name="label_orientation" msgid="2853142581990496477">"การวางแนว"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"หน้า"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"ทั้ง <xliff:g id="PAGE_COUNT">%1$s</xliff:g> หน้า"</string>
+    <string name="template_page_range" msgid="428638530038286328">"ช่วง <xliff:g id="PAGE_COUNT">%1$s</xliff:g> หน้า"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"เช่น 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"ตัวอย่างก่อนพิมพ์"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"ติดตั้งโปรแกรมดู PDF เพื่อดูหน้าตัวอย่าง"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index d94627e..70365e7 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Laki ng papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Kulay"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Oryentasyon"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Mga Page"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Lahat ng <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"Hanay ng <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"hal. 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Preview sa pag-print"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Mag-install ng PDF viewer para sa pag-preview"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index fab011e..ea803f65 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Kağıt boyutu:"</string>
     <string name="label_color" msgid="1108690305218188969">"Renkli"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Sayfa yönü"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Sayfa"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> sayfanın tamamı"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> sayfalık aralık"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ör. 1-5,8,11-13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Yazdırmayı önizle"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"Önizlemek için PDF görüntüleyici yükleyin"</string>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 2471d8b..1ff57a7 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"کاغذ کا سائز:"</string>
     <string name="label_color" msgid="1108690305218188969">"رنگ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"سمت بندی"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"صفحات"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"سبھی <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> کی رینج"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"‏مثلاً ‎1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"پرنٹ کا پیش منظر"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"‏پیش منظر کیلئے PDF ناظر انسٹال کریں"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index 71787f3..8ab3410 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Qog‘oz o‘lchami:"</string>
     <string name="label_color" msgid="1108690305218188969">"Rang"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Joylashuv"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"Sahifalar"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"Barchasi (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+    <string name="template_page_range" msgid="428638530038286328">"O‘zgarish chegarasi (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"masalan: 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Chop qilishni oldindan ko‘rish"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"PDF ko‘rsatuvchi dasturni o‘rnatish"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 3cf1173..cf452c9 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -25,12 +25,9 @@
     <string name="label_paper_size_summary" msgid="5668204981332138168">"紙張大小:"</string>
     <string name="label_color" msgid="1108690305218188969">"色彩"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
-    <!-- no translation found for label_pages (7768589729282182230) -->
-    <skip />
-    <!-- no translation found for template_all_pages (3322235982020148762) -->
-    <skip />
-    <!-- no translation found for template_page_range (428638530038286328) -->
-    <skip />
+    <string name="label_pages" msgid="7768589729282182230">"頁面"</string>
+    <string name="template_all_pages" msgid="3322235982020148762">"全部 <xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
+    <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"例如:1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"列印預覽"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"安裝預覽所需的 PDF 檢視器"</string>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index c5f18975..8d42ecd 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -18,8 +18,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Na-capture ang ulat ng bug"</string>
-    <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
-    <skip />
+    <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Mag-swipe pakaliwa upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pindutin upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ipakita ang mensaheng ito sa susunod"</string>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a038899..686f865 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -74,6 +74,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+    <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
 
     <!-- WindowManager -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
@@ -154,6 +155,13 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name=".qs.tiles.HotspotTile$APChangedReceiver"
+                androidprv:primaryUserOnly="true">
+            <intent-filter>
+                <action android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+
         <activity android:name=".usb.UsbStorageActivity"
                   android:label="@*android:string/usb_storage_activity_title"
                   android:excludeFromRecents="true">
diff --git a/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml b/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
index 7a62212..0a00d14 100644
--- a/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
@@ -15,16 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
     <size
-        android:width="64dp"
-        android:height="64dp"/>
+        android:width="64.0dp"
+        android:height="64.0dp"/>
 
     <viewport
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"/>
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0"/>
 
     <path
-        android:fill="#00000000"
-        android:stroke="#CCCCCC"
-        android:strokeWidth="1.0"
-        android:pathData="M12.0,11.0c-1.1,0.0 -2.0,0.9 -2.0,2.0c0.0,1.1 0.9,2.0 2.0,2.0c1.1,0.0 2.0,-0.9 2.0,-2.0C14.0,11.9 13.1,11.0 12.0,11.0zM18.0,13.0c0.0,-3.3 -2.7,-6.0 -6.0,-6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,2.2 1.2,4.1 3.0,5.2l1.0,-1.7c-1.2,-0.7 -2.0,-2.0 -2.0,-3.4c0.0,-2.2 1.8,-4.0 4.0,-4.0s4.0,1.8 4.0,4.0c0.0,1.5 -0.8,2.8 -2.0,3.4l1.0,1.7C16.8,17.1 18.0,15.2 18.0,13.0zM12.0,3.0C6.5,3.0 2.0,7.5 2.0,13.0c0.0,3.7 2.0,6.9 5.0,8.6l1.0,-1.7c-2.4,-1.4 -4.0,-4.0 -4.0,-6.9c0.0,-4.4 3.6,-8.0 8.0,-8.0s8.0,3.6 8.0,8.0c0.0,3.0 -1.6,5.5 -4.0,6.9l1.0,1.7c3.0,-1.7 5.0,-5.0 5.0,-8.6C22.0,7.5 17.5,3.0 12.0,3.0z"/>
+        android:fill="#4DFFFFFF"
+        android:pathData="M35.099998,28.500000c0.600000,-1.400000 0.900000,-2.900000 0.900000,-4.500000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-1.600000,0.000000 -3.100000,0.300000 -4.500000,0.900000l3.200000,3.200000c0.400000,-0.100000 0.800000,-0.100000 1.200000,-0.100000c4.400000,0.000000 8.000000,3.600000 8.000000,8.000000c0.000000,0.400000 0.000000,0.800000 -0.100000,1.300000L35.099998,28.500000zM24.000000,8.000000c8.800000,0.000000 16.000000,7.200000 16.000000,16.000000c0.000000,2.700000 -0.700000,5.200000 -1.900000,7.500000l2.900000,2.900000c1.900000,-3.000000 3.000000,-6.600000 3.000000,-10.400000c0.000000,-11.000000 -9.000000,-20.000000 -20.000000,-20.000000c-3.800000,0.000000 -7.400000,1.100000 -10.400000,2.900000l2.900000,2.900000C18.700001,8.700000 21.299999,8.000000 24.000000,8.000000zM6.500000,5.000000L4.000000,7.500000l4.200000,4.200000C5.600000,15.100000 4.000000,19.400000 4.000000,24.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-3.500000 1.100000,-6.800000 3.100000,-9.400000l2.900000,2.900000C12.700000,19.400000 12.000000,21.600000 12.000000,24.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-1.300000 0.300000,-2.500000 0.900000,-3.600000l3.200000,3.200000c0.000000,0.100000 0.000000,0.300000 0.000000,0.400000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c0.100000,0.000000 0.300000,0.000000 0.400000,0.000000l0.000000,0.000000l0.000000,0.000000l15.000000,15.000000l2.500000,-2.500000L8.500000,7.000000L6.500000,5.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml b/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
index 3ccdd81..01cb0ab 100644
--- a/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
@@ -15,14 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
     <size
-        android:width="64dp"
-        android:height="64dp"/>
+        android:width="64.0dp"
+        android:height="64.0dp"/>
 
     <viewport
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"/>
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0"/>
 
     <path
         android:fill="#FFFFFFFF"
-        android:pathData="M12.0,11.0c-1.1,0.0 -2.0,0.9 -2.0,2.0c0.0,1.1 0.9,2.0 2.0,2.0c1.1,0.0 2.0,-0.9 2.0,-2.0C14.0,11.9 13.1,11.0 12.0,11.0zM18.0,13.0c0.0,-3.3 -2.7,-6.0 -6.0,-6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,2.2 1.2,4.1 3.0,5.2l1.0,-1.7c-1.2,-0.7 -2.0,-2.0 -2.0,-3.4c0.0,-2.2 1.8,-4.0 4.0,-4.0s4.0,1.8 4.0,4.0c0.0,1.5 -0.8,2.8 -2.0,3.4l1.0,1.7C16.8,17.1 18.0,15.2 18.0,13.0zM12.0,3.0C6.5,3.0 2.0,7.5 2.0,13.0c0.0,3.7 2.0,6.9 5.0,8.6l1.0,-1.7c-2.4,-1.4 -4.0,-4.0 -4.0,-6.9c0.0,-4.4 3.6,-8.0 8.0,-8.0s8.0,3.6 8.0,8.0c0.0,3.0 -1.6,5.5 -4.0,6.9l1.0,1.7c3.0,-1.7 5.0,-5.0 5.0,-8.6C22.0,7.5 17.5,3.0 12.0,3.0z"/>
+        android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 3e4c1f6..85668de 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -62,7 +62,7 @@
             android:visibility="invisible"
             android:src="@drawable/recents_dismiss_light" />
     </com.android.systemui.recents.views.TaskBarView>
-    <FrameLayout
+    <com.android.systemui.recents.views.TaskFooterView
         android:id="@+id/lock_to_app"
         android:layout_width="match_parent"
         android:layout_height="@dimen/recents_task_view_lock_to_app_button_height"
@@ -82,7 +82,7 @@
             android:fontFamily="sans-serif-medium"
             android:singleLine="true"
             android:textAllCaps="true" />
-    </FrameLayout>
+    </com.android.systemui.recents.views.TaskFooterView>
 </com.android.systemui.recents.views.TaskView>
 
 
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index e75946a..91a1a06 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"إغلاق اللوحة"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"وقت أكثر"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"وقت أقل"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2-3 غيغابايت من البيانات المعطلة"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4 غيغابايت من البيانات المعطلة"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"البيانات الخلوية معطلة"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"البيانات معطلة"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"عطل جهازك البيانات نظرًا لبلوغها الحد الذي تم تعيينه.\n\nعلمًا بأن إعادتها قد يؤدي إلى تحمل رسوم من قبل مشغّل شبكة الجوّال."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"تشغيل البيانات"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"لا يوجد اتصال إنترنت"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi متصل"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"‏جارٍ البحث عن GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"بدون إزعاج، بما في ذلك المنبهات"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"بدون مقاطعات"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"المقاطعات ذات الأولوية فقط"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"التنبيه المقبل في <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"التنبيه المقبل في <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"لن تسمع المنبهات في <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"الإشعارات الأقل إلحاحًا أدناه"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"انقر مرة أخرى للفتح"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"فتح إعدادات وضع توفير الطاقة"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"المحتويات مخفية"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"الخروج من وضع الضيف"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> سيبدأ التقاط كل شيء يتم عرضه على الشاشة."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"عدم الإظهار مرة أخرى"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"البدء الآن"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 3412c2a..c50e0e9 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Zavřít panel"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Delší doba"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Kratší doba"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data 2G a 3G jsou vypnuta"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data 4G jsou vypnuta"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilní data jsou vypnuta"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data jsou vypnuta"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Zařízení datové přenosy vypnulo, protože dosáhlo limitu, který jste nastavili.\n\nJejich opětovné zapnutí může vézt k účtování poplatků operátorem."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Zapnout data"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Žádné přip. k internetu"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: připojeno"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhledávání satelitů GPS"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Přejeďte prstem doleva: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Žádná přerušení, ani budíky"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Žádná vyrušení"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Pouze prioritní vyrušení"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Další budík je nastaven na: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Další budík: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Neuslyšíte budík v <xliff:g id="ALARM_TIME">%s</xliff:g>."</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Méně urgentní oznámení níže"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Oznámení otevřete opětovným klepnutím"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otevřít nastavení režimu Úspora baterie"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Ukončit relaci hosta"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> začne zaznamenávat vše, co je zobrazeno na obrazovce."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Tuto zprávu příště nezobrazovat"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Spustit"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index dc62683..de11049 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -214,7 +214,7 @@
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi slået fra"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Der er ingen tilgængelige gemte netværk"</string>
     <string name="quick_settings_cast_title" msgid="1893629685050355115">"Cast skærm"</string>
-    <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
+    <string name="quick_settings_casting" msgid="6601710681033353316">"Caster"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Enhed uden navn"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Klar til at caste"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Der er ingen tilgængelige enheder"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 80fb802..10fdd06 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Sule paneel"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Rohkem aega"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Vähem aega"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G andmeside on väljalülitatud"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G andmeside on väljalülitatud"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mob. andmeside väljalülitatud"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Andmeside on väljalülitatud"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Seade lülitas andmeside välja, sest teie määratud limiit on täis.\n\nKui lülitate andmeside uuesti sisse, siis võivad lisanduda operaatori tasud."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Lülita andmeside sisse"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Interneti-ühendus puudub"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WiFi on ühendatud"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS-i otsimine"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Ei mingeid katkestusi, k.a äratus"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Mitte ühtegi katkestust"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Ainult prioriteetsed katkestused"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Teie järgmine äratus on <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Teie järgmine äratus on <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Te ei kuule äratust <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Vähem kiireloomulised märguanded on allpool"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Avamiseks puudutage uuesti"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Ava akusäästja seaded"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sisu on peidetud"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Välju külastaja režiimist"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> hakkab jäädvustama kõike, mida ekraanil kuvatakse."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Ära kuva uuesti"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Alusta kohe"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 214253a..c864170 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"بستن پانل"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"زمان بیشتر"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"زمان کمتر"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"داده شبکه سلولی خاموش است"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"داده خاموش است"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"دستگاه شما خاموش شد زیرا به حد تنظیم شده توسط شما رسید.\n\nروشن کردن مجدد آن می‌تواند به هزینه‌هایی از طرف شرکت مخابراتی شما منجر شود."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"روشن کردن داده"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"اتصال اینترنتی وجود ندارد"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi متصل شد"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"‏جستجو برای GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"بدون قطع شدن، شامل هشدارها"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"بدون وقفه"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"فقط وقفه‌های اولویت‌دار"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"هشدار بعدی شما در ساعت <xliff:g id="ALARM_TIME">%s</xliff:g> است"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"هشدار بعدی شما <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> است"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"هشدارتان را در ساعت <xliff:g id="ALARM_TIME">%s</xliff:g> نخواهید شنید"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"اعلان‌های کمتر فوری در زیر"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"برای باز کردن دوباره ضربه بزنید"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"باز کردن تنظیمات ذخیره کننده باتری"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>٪٪"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"خروج مهمان"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> شروع به ضبط هر چیزی می‌کند که در صفحه‌نمایش شما نمایش داده می‌شود."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"دوباره نشان داده نشود"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"اکنون شروع شود"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 0de52c5..e1d4661 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Sulje paneeli"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Lisää aikaa"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Vähennä aikaa"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobiilitiedonsiirto ei ole käytössä"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Tiedonsiirto ei ole käytössä"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Laitteesi poisti tiedonsiirron käytöstä, koska se saavutti asettamasi rajan.\n\nOperaattorisi saattaa veloittaa sinulta lisämaksuja, jos otat sen uudelleen käyttöön."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ota tiedonsiirto käyttöön"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ei internetyhteyttä"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi yhdistetty"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Haetaan GPS-yhteyttä"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Ei keskeytyksiä tai hälytyksiä"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Ei häiriöitä"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Vain tärkeät häiriöt"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Seuraava hälytysaika on <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Seuraava hälytysaika on <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Et kuule hälytystä klo <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Vähemmän kiireelliset ilmoitukset ovat alla"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Avaa napauttamalla uudelleen"</string>
@@ -293,12 +283,8 @@
     <!-- no translation found for battery_level_template (1609636980292580020) -->
     <skip />
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sisältö piilotettu"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Kirjaa vieras ulos"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alkaa tallentaa kaiken näytölläsi näkyvän."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Älä näytä uudelleen"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Aloita nyt"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index da0f6dd..1d586e1 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Zatvori ploču"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Više vremena"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Manje vremena"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G podaci isključeni"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G podaci isključeni"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilni podaci isključeni"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Podaci su isključeni"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Uređaj je isključio podatke jer je dosegnuo ograničenje koje ste postavili.\n\nAko ih ponovno uključite, mogući su dodatni troškovi za mobilne usluge."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Uključi podatke"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nema internetske veze"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Traženje GPS-a"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Bez prekida, uključujući alarme"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Bez prekida"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Samo prioritetni prekidi"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Vaš sljedeći alarm bit će u <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Vaš sljedeći alarm bit će u <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Nećete čuti alarm u <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitne obavijesti pri dnu"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite opet za otvaranje"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otvaranje postavki štednje baterije"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je skriven"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Izlaz iz gostujućeg načina"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> počet će snimati sve što se prikazuje na zaslonu."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj ponovo"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Započni sad"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index dbcc71d..8e39734 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Tutup panel"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Lebih lama"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Lebih cepat"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data 2G-3G nonaktif"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data 4G nonaktif"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Data seluler nonaktif"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data nonaktif"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Perangkat Anda menonaktifkan data karena data mencapai batas yang Anda setel.\n\nMengaktifkan kembali data dapat membuat Anda terkena biaya dari operator."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Aktifkan data"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Tidak ada sambungan internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tersambung"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Menelusuri GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Tanpa gangguan, termasuk alarm"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Tidak ada interupsi"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Hanya interupsi prioritas"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Alarm Anda berikutnya pukul <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Alarm Anda berikutnya hari <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Anda tidak akan mendengar alarm pukul <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang darurat di bawah"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Ketuk lagi untuk membuka"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Buka setelan penghemat baterai"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Konten tersembunyi"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Keluar dari tamu"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan mulai menangkap apa saja yang ditampilkan pada layar Anda."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Jangan tampilkan lagi"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Mulai sekarang"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 856eccf..90d648d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"パネルを閉じる"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"長くする"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"短くする"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"モバイルデータが無効になりました"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"データが無効になりました"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"設定された上限に達したため、端末のデータ接続が無効になりました。\n\n有効に戻すと、携帯通信会社から課金される可能性があります。"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"データ接続を有効にする"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"インターネット未接続"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi接続済み"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSで検索中"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"サイレント(アラームなど)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"サイレント"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"優先的な中断のみ"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"次のアラームは<xliff:g id="ALARM_TIME">%s</xliff:g>です"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"次のアラームは<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>です"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g>のアラームは鳴りません"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"緊急度の低い通知を下に表示"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"バッテリーセーバーの設定を開く"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"コンテンツが非表示"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"ゲストを終了"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>で、画面に表示されているコンテンツのキャプチャを開始します。"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"次回から表示しない"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"今すぐ開始"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index cccb7a8..b9f24ec 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -290,8 +290,7 @@
     <string name="battery_saver_notification_text" msgid="7796554871101546872">"მოწყობილობის წარმადობა შემცირებულია."</string>
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"ბატარეის დამზოგის პარამეტრების გახსნა"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
-    <!-- no translation found for notification_hidden_text (1135169301897151909) -->
-    <skip />
+    <string name="notification_hidden_text" msgid="1135169301897151909">"შიგთავსი დამალულია"</string>
     <!-- no translation found for guest_exit_guest (1619100760451149682) -->
     <skip />
     <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 90f66ae..6b2d46d 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"បិទ​បន្ទះ"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"ពេល​ច្រើនជាង"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"ពេល​តិចជាង"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ទិន្នន័យ​ចល័ត​បាន​បិទ"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ទិន្នន័យ​បាន​បិទ"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"ឧបករណ៍​របស់​អ្នក​បាន​បិទ​ទិន្នន័យ ព្រោះ​វា​បាន​ដល់​​កម្រិត​​ដែល​អ្នក​បាន​កំណត់។\n\nបើក​វា​ឡើង​វិញ​អាច​គិត​លុយ​ពី​ក្រុមហ៊ុន​បញ្ជូន​របស់​អ្នក។"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"បើក​ទិន្នន័យ"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"គ្មាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"បាន​ភ្ជាប់​វ៉ាយហ្វាយ"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"ស្វែងរក GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"រុញ​ឡើង​លើ​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"រុញ​ទៅ​ឆ្វេង​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"មិន​មានការ​ផ្អាក រួម​ទាំង​ការ​ជូនដំណឹង"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"គ្មាន​ការ​ផ្អាក"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"តែ​ការ​ផ្អាក​អាទិភាព​ប៉ុណ្ណោះ"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"ការ​ជូនដំណឹង​បន្ទាប់​របស់​អ្នក​គឺនៅម៉ោង <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ការ​ជូនដំណឹង​បន្ទាប់​របស់​អ្នក​គឺ​នៅ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"អ្នកនឹងមិនឮការជូន​ដំណឹងរបស់អ្នកនៅម៉ោង <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"ការ​ជូន​ដំណឹង​​មិន​សូវ​បន្ទាន់​ខាង​ក្រោម"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"ប៉ះ​ម្ដង​ទៀត ដើម្បី​បើក"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"បើក​ការ​កំណត់​កម្មវិធី​សន្សំ​ថ្ម"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"បាន​លាក់​មាតិកា"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"ភ្ញៀវ​ចាកចេញ"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> នឹង​ចាប់ផ្ដើម​ចាប់​យក​អ្វីៗ​គ្រប់យ៉ាង​ដែល​បង្ហាញ​លើ​អេក្រង់​របស់​អ្នក។"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"កុំ​បង្ហាញ​ម្ដងទៀត"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"ចាប់ផ្ដើម​ឥឡូវ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index cd2c580..4e05e9c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"패널 닫기"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"시간 늘리기"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"시간 줄이기"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"이동통신 데이터 사용 중지됨"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"데이터 사용 중지됨"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"기기가 설정 한도에 도달하여 데이터를 사용 중지했습니다.\n\n데이터를 다시 사용 설정하면 이동통신사로부터 대금이 청구될 수 있습니다."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"데이터 사용 설정"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"인터넷에 연결되지 않음"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 연결됨"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS 검색 중"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"검색"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"방해 금지(알람 포함)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"모든 알림 차단"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"최우선 알림만 수신"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"다음 알람 시각: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"다음 알람 일시: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g>에 알람을 들을 수 없습니다."</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"아래에 덜 급한 알림 표시"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"다시 탭하여 열기"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"배터리 세이버 설정 열기"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"숨겨진 콘텐츠"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"손님 모드 종료"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 화면에 표시된 모든 것을 캡처하기 시작합니다."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"다시 표시 안함"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"시작하기"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index f0ffafe..bdbcf64 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Uždaryti skydelį"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Daugiau laiko"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Mažiau laiko"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G duomenys išjungti"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G duomenys išjungti"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobiliojo ryšio duomenys išjungti"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Duomenys išjungti"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Įrenginys išjungė duomenis, nes buvo pasiektas nustatytas limitas.\n\nVėl juos įjungus gali būti taikomi operatoriaus mokesčiai."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Įjungti duomenis"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nėra interneto ryš."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Prisij. prie „Wi-Fi“"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Ieškoma GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Jokių pertraukčių, įskaitant signalus"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Jokių pertraukčių"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Tik prioritetinės pertrauktys"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Kito signalo laikas: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Kito signalo laikas: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> signalo negirdėsite"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Mažiau skubūs pranešimai toliau"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Palieskite dar kartą, kad atidarytumėte"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Atidaryti akumuliatoriaus tausojimo priemonės nustatymus"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Turinys paslėptas"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Išeiti iš svečio režimo"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"„<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ pradės fiksuoti viską, kas rodoma jūsų ekrane."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Daugiau neberodyti"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Pradėti dabar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 6c5cfe4..cf3996a 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Aizvērt paneli"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Ilgāk"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Mazāks laiks"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G dati ir atslēgti"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G dati ir atslēgti"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilie dati ir atslēgti"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dati ir atslēgti"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Jūsu ierīcē tika atslēgta datu lietošana, jo tika sasniegts jūsu noteiktais ierobežojums.\n\nJa atkal ieslēgsiet datu lietošanu, iespējams, jūsu mobilo sakaru operators iekasēs maksu."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ieslēgt datus"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nav interneta sav."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Izv. sav. ar Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Notiek GPS meklēšana..."</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Bez pārtraukumiem, tostarp bez signāliem"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Nepārtraukt"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Tikai prioritārie pārtraukumi"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Jūsu nākamā signāla laiks: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Jūsu nākamā signāla datums un laiks: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Jūs nedzirdēsiet iestatīto signālu: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Mazāk steidzami paziņojumi tiek rādīti tālāk"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Pieskarieties vēlreiz, lai atvērtu"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Atvērt akumulatora enerģijas taupīšanas režīma iestatījumus"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Saturs paslēpts"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Iziet no viesa režīma"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sāks uzņemt visu, kas tiks rādīts jūsu ekrānā."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Vairs nerādīt"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Sākt tūlīt"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index b8f6ce5..803e028 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Затвори ја плочата"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Повеќе време"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Помалку време"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобилните податоци се исклучени"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Податоците се исклучени"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Вашиот уред ги исклучи податоците затоа што го достигнаа лимитот што го поставивте.\n\nСо повторно вклучување, операторот може да ви наплати за тоа."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Вклучи податоци"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нема интернет"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Поврзано на Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Се пребарува за ГПС"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Пребарај"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Лизгај нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Лизгај налево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Без прекини, вклучувајќи аларми"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекини"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекини"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следниот аларм е во <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следниот аларм е <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Нема да го слушнете алармот во <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Долу се помалку итни известувања"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Допрете повторно за да се отвори"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Отвори ги поставките за штедачот на батерија"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содржините се скриени"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Излези како гостин"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ќе започне да презема сѐ што се прикажува на вашиот екран."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Не покажувај повторно"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Започни сега"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 1e29567..543f0f9 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -290,8 +290,7 @@
     <string name="battery_saver_notification_text" msgid="7796554871101546872">"Prestasi peranti dikurangkan."</string>
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Buka tetapan penjimat bateri"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
-    <!-- no translation found for notification_hidden_text (1135169301897151909) -->
-    <skip />
+    <string name="notification_hidden_text" msgid="1135169301897151909">"Kandungan tersembunyi"</string>
     <!-- no translation found for guest_exit_guest (1619100760451149682) -->
     <skip />
     <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 8d1347d..baefb81 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"प्यानल बन्द गर्नुहोस्"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"थप समय"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"कम समय"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"सेलुलर डेटा बन्द छ"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"तथ्याङ्क बन्द छ"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"तपाईंले सेट गर्नु भएको सीमा पुगेको हुनाले तपाईंको उपकरणले डेटा बंद गर्यो।\n\n यसलाई फिर्ता गर्दा आफ्नो वाहक बाट शुल्क लिन सक्छ।"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"डेटा खोल्नुहोस्"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"इन्टरनेट जडान छैन"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाइफाइ जडित"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSको लागि खोजी गर्दै"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"खोज्नुहोस्"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि माथि धिसार्नुहोस्"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"स्लाइड <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि बायाँ।"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"बिना रोकटोक, सचेतक सहित"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"कुनै रुकावटहरू छैन"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"प्राथमिकता रुकावटहरूमा मात्र"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"तपाईंको अर्को सचेतक <xliff:g id="ALARM_TIME">%s</xliff:g> मा छ"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"तपाईंको अर्को सचेतक <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> हो"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> मा तपाईंले आफ्नो सचेतक सुन्नुहुने छैन"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"तल कम जरुरी सूचनाहरू"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"खोल्न पुनः ट्याप गर्नुहोस्"</string>
@@ -290,14 +280,9 @@
     <string name="battery_saver_notification_text" msgid="7796554871101546872">"उपकरण कार्य क्षमता कम छ।"</string>
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"ब्याट्री सेभर सेटिङ्हरू खुला गर्नुहोस्"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
-    <!-- no translation found for notification_hidden_text (1135169301897151909) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="notification_hidden_text" msgid="1135169301897151909">"लुकेका सामाग्रीहरू"</string>
+    <string name="guest_exit_guest" msgid="1619100760451149682">"निकास अतिथि"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले आफ्नो स्क्रीनमा प्रदर्शित हुने सबै खिच्न शुरू गर्नेछ।"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"फेरि नदेखाउनुहोस्"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"अहिले सुरु गर्नुहोस्"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 3a93f38..19dadc4 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Închideți panoul"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Mai mult timp"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Mai puțin timp"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Datele 2G-3G sunt dezactivate"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Datele 4G sunt dezactivate"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Datele mobile sunt dezactivate"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Datele sunt dezactivate"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Dispozitivul dvs. a dezactivat conexiunea de date deoarece s-a atins limita pe care ați setat-o.\n\nReactivarea conexiunii poate genera aplicarea de taxe de către operator."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activați datele"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Fără conex. internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectat"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Fără întreruperi, inclusiv alarme"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Fără întreruperi"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Numai întreruperi cu prioritate"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Următoarea alarmă este setată la <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Următoarea alarmă este la <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Nu veți auzi alarma la <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Notificările mai puțin urgente mai jos"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Deschideți setările pentru economisirea bateriei"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conținutul este ascuns"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Închideți invitatul"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> va începe să captureze tot ceea ce se afișează pe ecran."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Nu se mai afișează"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Începeți acum"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index a04e6aa..8bbfd04 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Закрыть панель."</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Увеличить продолжительность."</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Уменьшить продолжительность."</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Передача мобильных данных отключена"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Передача данных отключена"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Передача данных отключена, поскольку достигнут установленный вами лимит.\n\nВы можете снова включить ее, однако за переданные данные оператор может взимать дополнительную плату."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Включить передачу данных"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нет интернет-подключения"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi подключено"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Поиск GPS"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Режим \"Не беспокоить\" (звук будильника отключен)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Не беспокоить"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Только приоритетные оповещения"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следующий будильник: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следующий будильник: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Следующий будильник: <xliff:g id="ALARM_TIME">%s</xliff:g>. Звук отключен."</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Показать менее важные оповещения"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Нажмите ещё раз, чтобы открыть"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Открыть настройки режима энергосбережения"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содержимое скрыто"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Выйти из гостевого режима"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"Приложение <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> получит доступ к изображению на экране устройства."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Больше не показывать"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Начать"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 905e8ce..7c5c702 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -290,8 +290,7 @@
     <string name="battery_saver_notification_text" msgid="7796554871101546872">"උපාංගය ක්‍රියාකාරිත්වය අඩු කරන ලදී."</string>
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"බැටරි ඉතිරි කරන්නා සැකසීම් විවෘත කරන්න"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
-    <!-- no translation found for notification_hidden_text (1135169301897151909) -->
-    <skip />
+    <string name="notification_hidden_text" msgid="1135169301897151909">"සැඟවුණු සම්බන්ධතා"</string>
     <!-- no translation found for guest_exit_guest (1619100760451149682) -->
     <skip />
     <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 3764406..08b6221 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Zavrieť panel"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Dlhší čas"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Kratší čas"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"dáta 2G–3G sú vypnuté"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"dáta 4G sú vypnuté"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilné dáta sú vypnuté"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dáta sú vypnuté"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Zariadenie vyplo dáta, pretože dosiahlo limit, ktorý ste nastavili.\n\nAk ich znova zapnete, môže to viesť k účtovaniu poplatkov operátora."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Zapnúť dáta"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Bez prip. na Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: pripojené"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhľadávanie satelitov GPS"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Prejdite prstom doľava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Žiadne prerušenia vrátane budíkov"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Žiadne prerušenia"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Iba prioritné prerušenia"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Ďalší budík: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Ďalší budík: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Váš budík o <xliff:g id="ALARM_TIME">%s</xliff:g> sa nespustí"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Menej naliehavé upozornenia sa nachádzajú nižšie"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Upozornenie otvoríte opätovným klepnutím"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otvorte nastavenia šetriča batérie"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Ukončiť režim hosťa"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"Aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> začne zaznamenávať všetok obsah zobrazený na vašej obrazovke."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Nabudúce nezobrazovať"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Spustiť"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 3b2f1b9..f08af24 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Затворите таблу"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Више времена"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Мање времена"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобилни пренос података је искључен"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Пренос података је искључен"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Уређај је искључио пренос података јер је достигао ограничење које сте поставили.\n\nАко га поново укључите, можда ће вам мобилни оператер наплатити трошкове."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Укључи пренос података"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Нема интернет везе"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi је повезан"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Тражи се GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Без прекида, укључујући аларме"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекида"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекиди"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следећи аларм је у <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следећи аларм: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Нећете чути аларм у <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Мање хитна обавештења су у наставку"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Додирните поново да бисте отворили"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Отворите подешавања Штедње батерије"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Садржај је сакривен"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Изађи из режима госта"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ће почети да снима све што се приказује на екрану."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Не приказуј поново"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Започни одмах"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 9a221ea..9c3e05a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -214,7 +214,7 @@
     <string name="quick_settings_cast_title" msgid="1893629685050355115">"Tuma skrini"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Inatuma"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Kifaa kisichokuwa na jina"</string>
-    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Tayari kwa kutuma"</string>
+    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Tayari kutuma"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Hakuna vifaa vilivyopatikana"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ung\'avu"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 7ebfda6..215d3e1 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ปิดแผงควบคุม"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"เวลามากขึ้น"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"เวลาน้อยลง"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ข้อมูลมือถือปิดอยู่"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ข้อมูลปิดอยู่"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"อุปกรณ์ของคุณปิดการใช้ข้อมูลเนื่องจากถึงขีดจำกัดที่คุณตั้งค่าไว้\n\nผู้ให้บริการอาจเรียกเก็บเงินหากเปิดใช้อีกครั้ง"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"เปิดใช้ข้อมูล"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ไม่มีอินเทอร์เน็ต"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"เชื่อมต่อ WiFi แล้ว"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"กำลังค้นหา GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"ไม่มีการรบกวนรวมถึงเสียงปลุก"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ไม่มีการรบกวน"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"เฉพาะเรื่องสำคัญเท่านั้น"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"การปลุกครั้งถัดไปของคุณคือเวลา <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"การปลุกครั้งถัดไปของคุณคือ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"คุณจะไม่ได้ยินเสียงปลุกในเวลา <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"การแจ้งเตือนที่เร่งด่วนน้อยด้านล่าง"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"เปิดการตั้งค่าโหมดประหยัดแบตเตอรี่"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"เนื้อหาที่ซ่อน"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"ออกจากโหมดผู้เยี่ยมชม"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะเริ่มจับภาพทุกอย่างที่แสดงบนหน้าจอ"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"ไม่ต้องแสดงข้อความนี้อีก"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"เริ่มเลย"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0e3e7dd..9387e9e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Isara ang panel"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Higit pang oras"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Mas kaunting oras"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Naka-off ang 2G-3G data"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Naka-off ang 4G data"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Naka-off ang cellular data"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Naka-off ang data"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Ini-off ng device mo ang data dahil naabot na nito ang limitasyong iyong itinakda.\n\nAng muling pag-o-on dito ay maaaring humantong sa mga singiling magmumula sa iyong carrier."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"I-on ang data"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Walang koneksyon sa Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"nakakonekta ang Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Naghahanap ng GPS"</string>
@@ -197,8 +191,7 @@
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> (na) Device)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Naka-off ang Bluetooth"</string>
-    <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
-    <skip />
+    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Walang available na mga magkapares na device"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Awtomatikong i-rotate"</string>
     <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Naka-lock ang pag-ikot"</string>
@@ -213,26 +206,18 @@
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"Mga Setting"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"Oras"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"Ako"</string>
-    <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
-    <skip />
-    <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
-    <skip />
+    <string name="quick_settings_user_title" msgid="4467690427642392403">"User"</string>
+    <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Bagong user"</string>
     <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
     <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Hindi Nakakonekta"</string>
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Walang Network"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Naka-off ang Wi-Fi"</string>
-    <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
-    <skip />
-    <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
-    <skip />
-    <!-- no translation found for quick_settings_casting (6601710681033353316) -->
-    <skip />
-    <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
-    <skip />
-    <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
-    <skip />
-    <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
-    <skip />
+    <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Walang available na naka-save na mga network"</string>
+    <string name="quick_settings_cast_title" msgid="1893629685050355115">"I-cast ang screen"</string>
+    <string name="quick_settings_casting" msgid="6601710681033353316">"Nagka-cast"</string>
+    <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Walang pangalang device"</string>
+    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Handang mag-cast"</string>
+    <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Walang available na mga device"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="quick_settings_inversion_label" msgid="8790919884718619648">"I-invert ang mga kulay"</string>
@@ -240,8 +225,7 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Marami pang setting"</string>
     <string name="quick_settings_done" msgid="3402999958839153376">"Tapos na"</string>
     <string name="quick_settings_connected" msgid="1722253542984847487">"Nakakonekta"</string>
-    <!-- no translation found for quick_settings_connecting (47623027419264404) -->
-    <skip />
+    <string name="quick_settings_connecting" msgid="47623027419264404">"Kumokonekta..."</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Nagte-tether"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</string>
@@ -252,8 +236,7 @@
     <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Lumampas sa limitasyon"</string>
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ang nagamit"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ang limitasyon"</string>
-    <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
-    <skip />
+    <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Babala sa <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="recents_empty_message" msgid="7883614615463619450">"Walang kamakailang mga app"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string>
     <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
@@ -266,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Mag-slide pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Walang mga pagkaantala, kabilang na ang mga alarma"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Walang mga paggambala"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Mga may priyoridad na paggambala lang"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Ang susunod mong alarma ay sa <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Ang susunod mong alarma ay <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Hindi mo maririnig ang alarma mo ng <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Nasa ibaba ang mga notification na hindi masyadong mahalaga"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"I-tap ulit upang buksan"</string>
@@ -302,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Buksan ang mga setting ng tagatipid ng baterya"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Nakatago ang mga content"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Lumabas bilang guest"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"Sisimulan ng i-capture ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang lahat ng ipinapakita sa iyong screen."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Huwag ipakitang muli"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Magsimula ngayon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 7a785d6..c00ec90 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Paneli kapatın"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Daha uzun süre"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Daha kısa süre"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G veri kullanımı kapalı"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G veri kullanımı kapalı"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Hücresel veri kapalı"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Veri kullanımı kapalı"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Ayarladığınız sınıra erişildiğinden cihazınız veri kullanımını kapattı.\n\nVeri kullanımını tekrar açmanız operatörünüzün ek ödemeler almasına neden olabilir."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Veri kullanımını aç"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"İnternet bağlantısı yok"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Kablosuz bağlandı"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS aranıyor"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Alarmlar dahil hiç kesinti yok"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Kesinti yok"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Sadece öncelikli kesintiler"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Bir sonraki alarmın saati: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Bir sonraki alarmınız: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> olarak ayarlanan alarmı duymayacaksınız"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az acil bildirimler aşağıdadır"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Açmak için tekrar hafifçe vurun"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Pil tasarrufu ayarlarını aç"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"%%<xliff:g id="LEVEL">%d</xliff:g>"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"İçerik gizlendi"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Misafir oturumundan çık"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görüntülenen her şeyi kaydetmeye başlayacak."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Bir daha gösterme"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Şimdi başla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 9e453b0..49abb62 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Закрити панель"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Більше часу"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Менше часу"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобільні дані вимкнено"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Дані вимкнено"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Пристрій вимкнув передавання даних, оскільки на ньому досягнуто встановленого вами ліміту.\n\nЯкщо передавання даних знову ввімкнути, оператор може стягувати з вас плату за це."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Увімкнути дані"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Немає з’єднання"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi під’єднано"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Виконується пошук GPS-сигналу"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Без сповіщень, зокрема сигналів будильника"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без сповіщень"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Лише пріоритетні сповіщення"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Наступний сигнал: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Наступний сигнал: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Сигнал не лунатиме о <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Менше термінових сповіщень нижче"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Торкніться знову, щоб відкрити"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Відкрийте налаштування режиму заощадження заряду акумулятора"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Вміст сховано"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Вийти з гостьового режиму"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> почне збирати всі дані, які відображаються на вашому екрані."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Більше не показувати"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Почати зараз"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 379fb1b..aa15d23 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"پینل بند کریں"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"مزید وقت"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"کم وقت"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"سیلولر ڈیٹا آف ہے"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ڈیٹا آف ہے"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"آپ کے آلہ نے ڈیٹا کو آف کر دیا کیونکہ یہ آپ کے متعینہ حد کو پہنچ گیا ہے۔\n\nاسے دوبارہ آن کرنے سے آپ کے کیریئر کی جانب سے چارجز عائد ہو سکتے ہیں۔"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ڈیٹا آن کریں"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"کوئی انٹرنیٹ کنکشن نہیں"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"‏Wi-Fi مربوط ہے"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"‏GPS کی تلاش کر رہا ہے"</string>
@@ -197,7 +191,7 @@
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوٹوتھ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوٹوتھ (<xliff:g id="NUMBER">%d</xliff:g> آلات)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوٹوتھ آف ہے"</string>
-    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"کوئی جوڑ بنائے ہوئے آلات دستیاب نہیں ہیں"</string>
+    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"کوئی جوڑا بنائے ہوئے آلات دستیاب نہیں ہیں"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"چمکیلا پن"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"خود کار طور پر گھمائیں"</string>
     <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"گردش مقفل ہے"</string>
@@ -242,7 +236,7 @@
     <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"حد سے زیادہ"</string>
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> استعمال کردہ"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> حد"</string>
-    <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> انتباہ"</string>
+    <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string>
     <string name="recents_empty_message" msgid="7883614615463619450">"کوئی حالیہ ایپس نہیں ہیں"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ایپلیکیشن کی معلومات"</string>
     <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"لاک ٹو ایپ"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"تلاش کریں"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> کیلئے اوپر سلائیڈ کریں۔"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> کیلئے بائیں سلائیڈ کریں۔"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"الارمز کے بشمول، کوئی مداخلتیں نہیں ہیں"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"کوئی مداخلتیں نہیں ہیں"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"صرف ترجیحی مداخلتیں"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"آپ کا اگلا الارم بوقت <xliff:g id="ALARM_TIME">%s</xliff:g> ہے"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"آپ کا اگلا الارم <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> ہے"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"آپ کو بوقت <xliff:g id="ALARM_TIME">%s</xliff:g> اپنا الارم سنائی نہیں دیگا"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"‎+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>‎"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"کم اہم اطلاعات ذیل میں ہیں"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"کھولنے کیلئے دوبارہ تھپتھپائیں"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"بیٹری سیور کی ترتیبات کھولیں"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"‎<xliff:g id="LEVEL">%d</xliff:g>%%‎"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"مواد مخفی ہیں"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"مہمان سے باہر نکلیں"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> آپ کی اسکرین پر ڈسپلے ہونے والی ہر چیز کو کیپچر کرنا شروع کر دیگی۔"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"دوبارہ نہ دکھائیں"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"ابھی شروع کریں"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d413ed7..bf32e6c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -166,18 +166,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Đóng bảng điều khiển"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Nhiều thời gian hơn"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Ít thời gian hơn"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Dữ liệu 2G-3G bị tắt"</string>
+    <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Dữ liệu 4G bị tắt"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Dữ liệu di động bị tắt"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dữ liệu bị tắt"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Thiết bị của bạn bị tắt dữ liệu do đã đạt đến giới hạn bạn đã đặt.\n\nViệc bật lại dữ liệu có thể dẫn tới các khoản phí từ nhà cung cấp dịch vụ của bạn."</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Bật dữ liệu"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ko có k.nối Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Đã kết nối Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Đang tìm kiếm GPS"</string>
@@ -255,16 +249,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"Không có gián đoạn, bao gồm báo thức"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Không có gián đoạn nào"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Chỉ các gián đoạn ưu tiên"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"Lần báo thức tiếp theo của bạn vào lúc <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Lần báo thức tiếp theo của bạn là <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"Bạn sẽ không nghe thấy báo thức lúc <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Thông báo ít khẩn cấp hơn bên dưới"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Nhấn lại để mở"</string>
@@ -291,12 +281,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Mở cài đặt trình tiết kiệm pin"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Nội dung bị ẩn"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"Thoát chế độ khách"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ bắt đầu chụp mọi thứ hiển thị trên màn hình."</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"Không hiển thị lại"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"Bắt đầu ngay"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 2d88348..92ee5a2 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -224,7 +224,7 @@
     <string name="quick_settings_cast_title" msgid="1893629685050355115">"投射屏幕"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"正在投射"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"未命名设备"</string>
-    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"准备好投射"</string>
+    <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"已准备好投射"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"没有可用设备"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
@@ -239,7 +239,7 @@
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手电筒"</string>
     <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"移动数据网络"</string>
-    <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"数据流量消耗"</string>
+    <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"流量使用情况"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩余流量"</string>
     <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"超出上限"</string>
     <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用<xliff:g id="DATA_USED">%s</xliff:g>"</string>
@@ -292,8 +292,7 @@
     <string name="battery_saver_notification_text" msgid="7796554871101546872">"设备性能已减降。"</string>
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"打开节电助手设置"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
-    <!-- no translation found for notification_hidden_text (1135169301897151909) -->
-    <skip />
+    <string name="notification_hidden_text" msgid="1135169301897151909">"内容已隐藏"</string>
     <!-- no translation found for guest_exit_guest (1619100760451149682) -->
     <skip />
     <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f4c4e14..2e3878d 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"關閉面板"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"更多時間"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"較少時間"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"流動數據連線已關閉"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"數據連線已關閉"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"數據流量已達到您所設定的上限,因此裝置關閉了數據連線。\n\n若重新開啟數據連線,流動網絡供應商可能會向您收費。"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"開啟數據連線"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"沒有互聯網連線"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已連線"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"不允許干擾 (包含鬧鐘)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"不允許干擾"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"僅限優先干擾"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"下次鬧鐘時間:<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"下次鬧鐘時間:<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"您不會聽到<xliff:g id="ALARM_TIME">%s</xliff:g> 的鬧鐘"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"還有 <xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g> 則通知"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"不太緊急的通知會在下方顯示"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"開啟省電設定"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"結束訪客模式"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 將開始擷取您的螢幕上顯示的內容。"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"不用再顯示"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2ffa320..840778b 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -168,18 +168,12 @@
     <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"關閉面板"</string>
     <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"更多時間"</string>
     <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"更少時間"</string>
-    <!-- no translation found for data_usage_disabled_dialog_3g_title (2626865386971800302) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_4g_title (4629078114195977196) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_mobile_title (5793456071535876132) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_title (8723412000355709802) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog (6468718338038876604) -->
-    <skip />
-    <!-- no translation found for data_usage_disabled_dialog_enable (5538068036107372895) -->
-    <skip />
+    <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>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"行動數據連線已關閉"</string>
+    <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"數據連線已關閉"</string>
+    <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"數據流量已達您所設定的上限,因此裝置關閉了數據連線。\n\n如果重新開啟數據連線,行動通訊業者可能會向您收費。"</string>
+    <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"開啟數據連線"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"沒有網際網路連線"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已連線"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
@@ -257,16 +251,12 @@
     <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <!-- no translation found for zen_no_interruptions_with_warning (2522931836819051293) -->
-    <skip />
+    <string name="zen_no_interruptions_with_warning" msgid="2522931836819051293">"不允許干擾 (包含鬧鐘)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"不允許干擾"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"僅限優先干擾"</string>
-    <!-- no translation found for zen_alarm_information_time (5235772206174372272) -->
-    <skip />
-    <!-- no translation found for zen_alarm_information_day_time (8422733576255047893) -->
-    <skip />
-    <!-- no translation found for zen_alarm_warning (6873910860111498041) -->
-    <skip />
+    <string name="zen_alarm_information_time" msgid="5235772206174372272">"下次鬧鐘時間:<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"下次鬧鐘時間:<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
+    <string name="zen_alarm_warning" msgid="6873910860111498041">"您不會聽到<xliff:g id="ALARM_TIME">%s</xliff:g> 的鬧鐘"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"還有 <xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g> 則通知"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"較不緊急的通知會顯示在下方"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
@@ -293,12 +283,8 @@
     <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"開啟節約耗電量設定"</string>
     <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
-    <!-- no translation found for guest_exit_guest (1619100760451149682) -->
-    <skip />
-    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
-    <skip />
-    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
-    <skip />
-    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
-    <skip />
+    <string name="guest_exit_guest" msgid="1619100760451149682">"結束訪客模式"</string>
+    <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 將開始擷取您的螢幕上顯示的內容。"</string>
+    <string name="media_projection_remember_text" msgid="3103510882172746752">"不要再顯示"</string>
+    <string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 627f11c..e9fe09e 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -23,6 +23,7 @@
     <color name="system_bar_background_opaque">#ff000000</color>
     <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
     <color name="system_bar_background_transparent">#00000000</color>
+    <color name="system_bar_background_warning">#fff4511e</color><!-- deep orange 600 -->
     <color name="notification_panel_solid_background">#ff000000</color>
     <drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
     <color name="status_bar_recents_app_label_color">#ffffffff</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 94fcc23..8b11ef1 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -164,5 +164,8 @@
 
     <!-- Volume: time to delay dismissing the volume panel after a click is performed -->
     <integer name="volume_panel_dismiss_delay">200</integer>
+
+    <!-- Hotspot tile: number of days to show after feature is used. -->
+    <integer name="days_to_show_hotspot">30</integer>
 </resources>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index fc08cf4..93766af 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -30,11 +30,12 @@
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.Listenable;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.volume.VolumeComponent;
 
@@ -244,16 +245,16 @@
         void collapsePanels();
         Looper getLooper();
         Context getContext();
+        List<QSTile<?>> getTiles();
         BluetoothController getBluetoothController();
         LocationController getLocationController();
         RotationLockController getRotationLockController();
-        List<QSTile<?>> getTiles();
         NetworkController getNetworkController();
         ZenModeController getZenModeController();
-        TetheringController getTetheringController();
+        HotspotController getHotspotController();
         CastController getCastController();
-        VolumeComponent getVolumeComponent();
         FlashlightController getFlashlightController();
+        KeyguardMonitor getKeyguardMonitor();
     }
 
     public static class State {
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 ab952c6..531ac31 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -30,6 +30,7 @@
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.util.LinkedHashMap;
 import java.util.Set;
@@ -41,11 +42,14 @@
 
     private final CastController mController;
     private final CastDetailAdapter mDetailAdapter;
+    private final KeyguardMonitor mKeyguard;
+    private final Callback mCallback = new Callback();
 
     public CastTile(Host host) {
         super(host);
         mController = host.getCastController();
         mDetailAdapter = new CastDetailAdapter();
+        mKeyguard = host.getKeyguardMonitor();
     }
 
     @Override
@@ -64,9 +68,11 @@
         if (DEBUG) Log.d(TAG, "setListening " + listening);
         if (listening) {
             mController.addCallback(mCallback);
+            mKeyguard.addCallback(mCallback);
         } else {
             mController.setDiscovering(false);
             mController.removeCallback(mCallback);
+            mKeyguard.removeCallback(mCallback);
         }
     }
 
@@ -84,7 +90,7 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        state.visible = true;
+        state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
         state.label = mContext.getString(R.string.quick_settings_cast_title);
         state.value = false;
         final Set<CastDevice> devices = mController.getCastDevices();
@@ -109,11 +115,16 @@
                 : mContext.getString(R.string.quick_settings_cast_device_default_name);
     }
 
-    private final CastController.Callback mCallback = new CastController.Callback() {
+    private final class Callback implements CastController.Callback, KeyguardMonitor.Callback {
         @Override
         public void onCastDevicesChanged() {
             refreshState();
         }
+
+        @Override
+        public void onKeyguardChanged() {
+            refreshState();
+        }
     };
 
     private final class CastDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index b610cf3..75e3bc1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -62,7 +62,9 @@
         if (arg instanceof Boolean) {
             state.value = (Boolean) arg;
         }
-        state.visible = mFlashlightController.isAvailable();
+        // Always show the tile when the flashlight is on. This is needed because
+        // the camera is not available while it is being used for the flashlight.
+        state.visible = state.value || mFlashlightController.isAvailable();
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         state.iconId = state.value
                 ? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
@@ -77,4 +79,9 @@
     public void onFlashlightError() {
         refreshState(false);
     }
+
+    @Override
+    public void onFlashlightAvailabilityChanged(boolean available) {
+        refreshState();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index f2ba558..35dfdda 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,45 +16,98 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
-import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 /** Quick settings tile: Hotspot **/
-public class HotspotTile extends QSTile<QSTile.State> {
-    private static final Intent TETHER_SETTINGS = new Intent()
-            .setClassName("com.android.settings", "com.android.settings.TetherSettings");
+public class HotspotTile extends QSTile<QSTile.BooleanState> {
+    private static final String KEY_LAST_USED_DATE = "lastUsedDate";
+    private static final long MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
 
-    // TODO: implement. see com.android.settings.TetherSettings
-
-    private final TetheringController mController;
+    private final HotspotController mController;
+    private final KeyguardMonitor mKeyguard;
+    private final Callback mCallback = new Callback();
+    private final long mTimeToShowTile;
 
     public HotspotTile(Host host) {
         super(host);
-        mController = host.getTetheringController();
+        mController = host.getHotspotController();
+        mKeyguard = host.getKeyguardMonitor();
+
+        mTimeToShowTile = MILLIS_PER_DAY
+                * mContext.getResources().getInteger(R.integer.days_to_show_hotspot);
     }
 
     @Override
-    protected State newTileState() {
-        return new State();
+    protected BooleanState newTileState() {
+        return new BooleanState();
     }
 
     @Override
     public void setListening(boolean listening) {
-
+        if (listening) {
+            mController.addCallback(mCallback);
+            mKeyguard.addCallback(mCallback);
+        } else {
+            mController.removeCallback(mCallback);
+            mKeyguard.removeCallback(mCallback);
+        }
     }
 
     @Override
     protected void handleClick() {
-        mHost.startSettingsActivity(TETHER_SETTINGS);
+        final boolean isEnabled = (Boolean) mState.value;
+        mController.setHotspotEnabled(!isEnabled);
     }
 
     @Override
-    protected void handleUpdateState(State state, Object arg) {
-        state.visible = mController != null;
+    protected void handleUpdateState(BooleanState state, Object arg) {
+        state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing())
+                && mController.isHotspotSupported() && isHotspotRecentlyUsed();
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
-        state.iconId = R.drawable.ic_qs_hotspot_off;
+
+        state.value = mController.isHotspotEnabled();
+        state.iconId = state.visible && state.value ? R.drawable.ic_qs_hotspot_on
+                : R.drawable.ic_qs_hotspot_off;
+    }
+
+    private boolean isHotspotRecentlyUsed() {
+        long lastDay = getSharedPrefs(mContext).getLong(KEY_LAST_USED_DATE, 0);
+        return (System.currentTimeMillis() - lastDay) < mTimeToShowTile;
+    }
+
+    private static SharedPreferences getSharedPrefs(Context context) {
+        return context.getSharedPreferences(context.getPackageName(), 0);
+    }
+
+    private final class Callback implements HotspotController.Callback, KeyguardMonitor.Callback {
+        @Override
+        public void onHotspotChanged(boolean enabled) {
+            refreshState();
+        }
+
+        @Override
+        public void onKeyguardChanged() {
+            refreshState();
+        }
+    };
+
+    /**
+     * This will catch broadcasts for changes in hotspot state so we can show
+     * the hotspot tile for a number of days after use.
+     */
+    public static class APChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            long currentTime = System.currentTimeMillis();
+            getSharedPrefs(context).edit().putLong(KEY_LAST_USED_DATE, currentTime).commit();
+        }
     }
 }
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 04f1eb5..c4dd643 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -18,6 +18,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
 
@@ -25,10 +26,13 @@
 public class LocationTile extends QSTile<QSTile.BooleanState> {
 
     private final LocationController mController;
+    private final KeyguardMonitor mKeyguard;
+    private final Callback mCallback = new Callback();
 
     public LocationTile(Host host) {
         super(host);
         mController = host.getLocationController();
+        mKeyguard = host.getKeyguardMonitor();
     }
 
     @Override
@@ -40,8 +44,10 @@
     public void setListening(boolean listening) {
         if (listening) {
             mController.addSettingsChangedCallback(mCallback);
+            mKeyguard.addCallback(mCallback);
         } else {
             mController.removeSettingsChangedCallback(mCallback);
+            mKeyguard.removeCallback(mCallback);
         }
     }
 
@@ -59,7 +65,7 @@
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
         final boolean locationEnabled =  mController.isLocationEnabled();
-        state.visible = true;
+        state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
         state.value = locationEnabled;
         if (locationEnabled) {
             state.iconId = R.drawable.ic_qs_location_on;
@@ -76,10 +82,16 @@
         }
     }
 
-    private final LocationSettingsChangeCallback mCallback = new LocationSettingsChangeCallback() {
+    private final class Callback implements LocationSettingsChangeCallback,
+            KeyguardMonitor.Callback {
         @Override
         public void onLocationSettingsChanged(boolean enabled) {
             refreshState();
         }
+
+        @Override
+        public void onKeyguardChanged() {
+            refreshState();
+        }
     };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 66e5d14..591149c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -70,10 +71,13 @@
 
     // Task launching
     RecentsConfiguration mConfig;
-    Rect mWindowRect;
-    Rect mTaskStackBounds;
+    Rect mWindowRect = new Rect();
+    Rect mTaskStackBounds = new Rect();
+    Rect mSystemInsets = new Rect();
     TaskViewTransform mTmpTransform = new TaskViewTransform();
     int mStatusBarHeight;
+    int mNavBarHeight;
+    int mNavBarWidth;
 
     // Variables to keep track of if we need to start recents after binding
     View mStatusBarView;
@@ -81,15 +85,23 @@
     long mLastToggleTime;
 
     public AlternateRecentsComponent(Context context) {
+        Resources res = context.getResources();
         mContext = context;
         mSystemServicesProxy = new SystemServicesProxy(context);
         mHandler = new Handler();
         mConfig = RecentsConfiguration.reinitialize(context, mSystemServicesProxy);
         mWindowRect = mSystemServicesProxy.getWindowRect();
         mTaskStackBounds = new Rect();
-        mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mTaskStackBounds);
-        mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
+        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() {
@@ -150,7 +162,13 @@
         mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy);
         mConfig.updateOnConfigurationChange();
         mWindowRect = mSystemServicesProxy.getWindowRect();
-        mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mTaskStackBounds);
+        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);
+        }
         sLastScreenshot = null;
     }
 
@@ -301,7 +319,9 @@
         // Get the stack
         TaskStackView tsv = new TaskStackView(mContext, stack);
         TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
-        tsv.computeRects(mTaskStackBounds.width(), mTaskStackBounds.height() - mStatusBarHeight, 0, 0);
+        Rect taskStackBounds = new Rect(mTaskStackBounds);
+        taskStackBounds.bottom -= mSystemInsets.bottom;
+        tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
         tsv.setStackScrollToInitialState();
 
         // Find the running task in the TaskStack
@@ -325,8 +345,6 @@
 
         // Get the transform for the running task
         mTmpTransform = algo.getStackTransform(task, tsv.getStackScroll(), mTmpTransform);
-        mTmpTransform.rect.offset(mTaskStackBounds.left, mTaskStackBounds.top);
-        mTmpTransform.rect.offset(0, mStatusBarHeight);
         return new Rect(mTmpTransform.rect);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 5741f22..7d69b94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -32,18 +32,20 @@
 import android.util.Pair;
 import android.view.KeyEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewStub;
+import android.widget.FrameLayout;
 import android.widget.Toast;
 import com.android.systemui.R;
-import com.android.systemui.recents.misc.Console;
 import com.android.systemui.recents.misc.DebugTrigger;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 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.SpaceNode;
+import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.FullscreenTransitionOverlayView;
+import com.android.systemui.recents.views.DebugOverlayView;
 import com.android.systemui.recents.views.RecentsView;
 import com.android.systemui.recents.views.SystemBarScrimViews;
 import com.android.systemui.recents.views.ViewAnimation;
@@ -56,8 +58,7 @@
  * The main Recents activity that is started from AlternateRecentsComponent.
  */
 public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
-        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
-        FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks {
+        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
 
     // Actions and Extras sent from AlternateRecentsComponent
     final static String EXTRA_TRIGGERED_FROM_ALT_TAB = "extra_triggered_from_alt_tab";
@@ -73,17 +74,14 @@
     SystemBarScrimViews mScrimViews;
     ViewStub mEmptyViewStub;
     View mEmptyView;
-    ViewStub mFullscreenOverlayStub;
-    FullscreenTransitionOverlayView mFullScreenOverlayView;
+    DebugOverlayView mDebugOverlay;
 
     // Search AppWidget
     RecentsAppWidgetHost mAppWidgetHost;
     AppWidgetProviderInfo mSearchAppWidgetInfo;
     AppWidgetHostView mSearchAppWidgetHostView;
 
-
     // Runnables to finish the Recents activity
-    FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable();
     FinishRecentsRunnable mFinishLaunchHomeRunnable;
 
     /**
@@ -97,10 +95,6 @@
         Intent mLaunchIntent;
         ActivityOptions mLaunchOpts;
 
-        public FinishRecentsRunnable() {
-            // Do nothing
-        }
-
         /**
          * Creates a finish runnable that starts the specified intent, using the given
          * ActivityOptions.
@@ -151,8 +145,7 @@
             } else if (action.equals(ACTION_START_ENTER_ANIMATION)) {
                 // Try and start the enter animation (or restart it on configuration changed)
                 ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
-                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
-                        mFullScreenOverlayView, t));
+                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
                 onEnterAnimationTriggered();
             }
         }
@@ -187,11 +180,12 @@
 
     /** Updates the set of recent tasks */
     void updateRecentsTasks(Intent launchIntent) {
+        // Load all the tasks
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
         ArrayList<TaskStack> stacks = root.getStacks();
         if (!stacks.isEmpty()) {
-            mRecentsView.setBSP(root);
+            mRecentsView.setTaskStacks(root.getStacks());
         }
 
         // Update the configuration based on the launch intent
@@ -207,6 +201,23 @@
         mConfig.launchedToTaskId = launchIntent.getIntExtra(
                 AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_TASK_ID, -1);
 
+        // Mark the task that is the launch target
+        int taskStackCount = stacks.size();
+        if (mConfig.launchedToTaskId != -1) {
+            for (int i = 0; i < taskStackCount; i++) {
+                TaskStack stack = stacks.get(i);
+                ArrayList<Task> tasks = stack.getTasks();
+                int taskCount = tasks.size();
+                for (int j = 0; j < taskCount; j++) {
+                    Task t = tasks.get(j);
+                    if (t.key.id == mConfig.launchedToTaskId) {
+                        t.isLaunchTarget = true;
+                        break;
+                    }
+                }
+            }
+        }
+
         // Update the top level view's visibilities
         if (mConfig.launchedWithNoRecentTasks) {
             if (mEmptyView == null) {
@@ -286,9 +297,6 @@
     /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
     boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
         if (mVisible) {
-            // If we are mid-animation into Recents, reverse the animation now
-            if (mFullScreenOverlayView != null &&
-                mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
             // If we currently have filtered stacks, then unfilter those first
             if (checkFilteredStackState &&
                 mRecentsView.unfilterFilteredStacks()) return true;
@@ -299,8 +307,8 @@
                 dismissRecentsToHomeRaw(true);
                 return true;
             }
-            // Otherwise, try and return to the first Task in the stack
-            if (mRecentsView.launchFirstTask()) return true;
+            // Otherwise, try and return to the Task that Recents was launched from
+            if (mRecentsView.launchPreviousTask()) return true;
             // If none of the other cases apply, then just go Home
             dismissRecentsToHomeRaw(true);
             return true;
@@ -323,9 +331,6 @@
     /** Dismisses Recents directly to Home if we currently aren't transitioning. */
     boolean dismissRecentsToHome(boolean animated) {
         if (mVisible) {
-            // If we are mid-animation into Recents, reverse the animation now
-            if (mFullScreenOverlayView != null &&
-                mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
             // Return to Home
             dismissRecentsToHomeRaw(animated);
             return true;
@@ -363,8 +368,8 @@
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
         mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
-        mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub);
         mScrimViews = new SystemBarScrimViews(this, mConfig);
+        inflateDebugOverlay();
 
         // Bind the search app widget when we first start up
         bindSearchBarAppWidget();
@@ -390,13 +395,6 @@
             e.printStackTrace();
         }
 
-        // Prepare the screenshot transition if necessary
-        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
-            mFullScreenOverlayView.setCallbacks(this);
-            mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
-        }
-
         // Update if we are getting a configuration change
         if (savedInstanceState != null) {
             mConfig.updateOnConfigurationChange();
@@ -404,6 +402,19 @@
         }
     }
 
+    /** Inflates the debug overlay if debug mode is enabled. */
+    void inflateDebugOverlay() {
+        if (mConfig.debugModeEnabled && mDebugOverlay == null) {
+            ViewGroup parent = (ViewGroup) findViewById(android.R.id.content).getRootView();
+            mDebugOverlay = new DebugOverlayView(this);
+            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT);
+            parent.addView(mDebugOverlay, lp);
+            mRecentsView.setDebugOverlay(mDebugOverlay);
+        }
+    }
+
     void onConfigurationChange() {
         // Update RecentsConfiguration
         mConfig = RecentsConfiguration.reinitialize(this,
@@ -411,8 +422,7 @@
 
         // Try and start the enter animation (or restart it on configuration changed)
         ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
-        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
-                mFullScreenOverlayView, t));
+        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
         onEnterAnimationTriggered();
     }
 
@@ -421,13 +431,13 @@
         super.onNewIntent(intent);
         setIntent(intent);
 
+        // Clear any debug rects
+        if (mDebugOverlay != null) {
+            mDebugOverlay.clear();
+        }
+
         // Update the recent tasks
         updateRecentsTasks(intent);
-
-        // Prepare the screenshot transition if necessary
-        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
-        }
     }
 
     @Override
@@ -531,17 +541,25 @@
 
     /** Called when debug mode is triggered */
     public void onDebugModeTriggered() {
+
         if (mConfig.developerOptionsEnabled) {
             SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
             if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
                 // Disable the debug mode
                 settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply();
+                mConfig.debugModeEnabled = false;
+                inflateDebugOverlay();
+                mDebugOverlay.disable();
             } else {
                 // Enable the debug mode
                 settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply();
+                mConfig.debugModeEnabled = true;
+                inflateDebugOverlay();
+                mDebugOverlay.enable();
             }
-            Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion +
-                    ") toggled, please restart Recents now", Toast.LENGTH_SHORT).show();
+            Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion + ") " +
+                (mConfig.debugModeEnabled ? "Enabled" : "Disabled") + ", please restart Recents now",
+                Toast.LENGTH_SHORT).show();
         }
     }
 
@@ -551,19 +569,6 @@
         mScrimViews.startEnterRecentsAnimation();
     }
 
-    /**** FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks Implementation ****/
-
-    @Override
-    public void onEnterAnimationComplete() {
-        // Reset the full screenshot transition view
-        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mFullScreenOverlayView.reset();
-
-            // Recycle the full screen screenshot
-            AlternateRecentsComponent.consumeLastScreenshot();
-        }
-    }
-
     /**** RecentsView.RecentsViewCallbacks Implementation ****/
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index a0cab5c..55711cf0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -309,19 +309,16 @@
      * Returns the task stack bounds in the current orientation. These bounds do not account for
      * the system insets.
      */
-    public void getTaskStackBounds(int width, int height, Rect taskStackBounds) {
-        if (hasSearchBarAppWidget()) {
-            Rect searchBarBounds = new Rect();
-            getSearchBarBounds(width, height, searchBarBounds);
-            if (isLandscape && transposeRecentsLayoutWithOrientation) {
-                // In landscape, the search bar appears on the left, so shift the task rect right
-                taskStackBounds.set(searchBarBounds.width(), 0, width, height);
-            } else {
-                // In portrait, the search bar appears on the top, so shift the task rect below
-                taskStackBounds.set(0, searchBarBounds.height(), width, height);
-            }
+    public void getTaskStackBounds(int windowWidth, int windowHeight, int topInset, int rightInset,
+                                   Rect taskStackBounds) {
+        Rect searchBarBounds = new Rect();
+        getSearchBarBounds(windowWidth, windowHeight, topInset, searchBarBounds);
+        if (isLandscape && transposeRecentsLayoutWithOrientation) {
+            // In landscape, the search bar appears on the left
+            taskStackBounds.set(searchBarBounds.right, topInset, windowWidth - rightInset, windowHeight);
         } else {
-            taskStackBounds.set(0, 0, width, height);
+            // In portrait, the search bar appears on the top (which already has the inset)
+            taskStackBounds.set(0, searchBarBounds.bottom, windowWidth, windowHeight);
         }
     }
 
@@ -329,19 +326,20 @@
      * Returns the search bar bounds in the current orientation.  These bounds do not account for
      * the system insets.
      */
-    public void getSearchBarBounds(int width, int height, Rect searchBarSpaceBounds) {
+    public void getSearchBarBounds(int windowWidth, int windowHeight, int topInset,
+                                   Rect searchBarSpaceBounds) {
         // Return empty rects if search is not enabled
-        if (!Constants.DebugFlags.App.EnableSearchLayout) {
-            searchBarSpaceBounds.set(0, 0, 0, 0);
-            return;
+        int searchBarSize = searchBarSpaceHeightPx;
+        if (!Constants.DebugFlags.App.EnableSearchLayout || !hasSearchBarAppWidget()) {
+            searchBarSize = 0;
         }
 
         if (isLandscape && transposeRecentsLayoutWithOrientation) {
             // In landscape, the search bar appears on the left
-            searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
+            searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
         } else {
             // In portrait, the search bar appears on the top
-            searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
+            searchBarSpaceBounds.set(0, topInset, windowWidth, topInset + searchBarSize);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 5fadc71..fb77751 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -38,6 +38,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
@@ -437,7 +438,9 @@
         Rect windowRect = new Rect();
         if (mWm == null) return windowRect;
 
-        mWm.getDefaultDisplay().getRectSize(windowRect);
+        Point p = new Point();
+        mWm.getDefaultDisplay().getRealSize(p);
+        windowRect.set(0, 0, p.x, p.y);
         return windowRect;
     }
 
@@ -467,4 +470,13 @@
     public Bitmap takeAppScreenshot() {
         return takeScreenshot();
     }
+
+    public void startActivityFromRecents(int taskId, ActivityOptions options) {
+        if (mIam != null) {
+            try {
+                mIam.startActivityFromRecents(taskId, options == null ? null : options.toBundle());
+            } catch (RemoteException e) {
+            }
+        }
+    }
 }
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 4cf9235..41874fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -77,6 +77,7 @@
     public TaskKey key;
     public TaskGrouping group;
     public int taskAffiliation;
+    public boolean isLaunchTarget;
     public Drawable applicationIcon;
     public Drawable activityIcon;
     public String activityLabel;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
new file mode 100644
index 0000000..9076818
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -0,0 +1,118 @@
+/*
+ * 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.recents.views;
+
+import android.animation.ObjectAnimator;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import com.android.systemui.recents.RecentsConfiguration;
+
+/* An outline provider that has a clip and outline that can be animated. */
+public class AnimateableViewBounds extends ViewOutlineProvider {
+
+    RecentsConfiguration mConfig;
+
+    View mSourceView;
+    Rect mClipRect = new Rect();
+    Rect mOutlineClipRect = new Rect();
+    int mCornerRadius;
+
+    ObjectAnimator mClipTopAnimator;
+    ObjectAnimator mClipBottomAnimator;
+
+    public AnimateableViewBounds(View source, int cornerRadius) {
+        mConfig = RecentsConfiguration.getInstance();
+        mSourceView = source;
+        mCornerRadius = cornerRadius;
+        mSourceView.setClipToOutline(true);
+        setClipTop(getClipTop());
+        setClipBottom(getClipBottom());
+        setOutlineClipBottom(getOutlineClipBottom());
+    }
+
+    @Override
+    public void getOutline(View view, Outline outline) {
+        outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
+                Math.max(mClipRect.top, mOutlineClipRect.top),
+                mSourceView.getMeasuredWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
+                mSourceView.getMeasuredHeight() - Math.max(mClipRect.bottom, mOutlineClipRect.bottom),
+                mCornerRadius);
+    }
+
+    /** Animates the top clip. */
+    void animateClipTop(int top, int duration) {
+        if (mClipTopAnimator != null) {
+            mClipTopAnimator.removeAllListeners();
+            mClipTopAnimator.cancel();
+        }
+        mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
+        mClipTopAnimator.setDuration(duration);
+        mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+        mClipTopAnimator.start();
+    }
+
+    /** Sets the top clip. */
+    public void setClipTop(int top) {
+        if (top != mClipRect.top) {
+            mClipRect.top = top;
+            mSourceView.invalidateOutline();
+        }
+    }
+
+    /** Returns the top clip. */
+    public int getClipTop() {
+        return mClipRect.top;
+    }
+
+    /** Animates the bottom clip. */
+    void animateClipBottom(int bottom, int duration) {
+        if (mClipTopAnimator != null) {
+            mClipTopAnimator.removeAllListeners();
+            mClipTopAnimator.cancel();
+        }
+        mClipTopAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
+        mClipTopAnimator.setDuration(duration);
+        mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+        mClipTopAnimator.start();
+    }
+
+    /** Sets the bottom clip. */
+    public void setClipBottom(int bottom) {
+        if (bottom != mClipRect.bottom) {
+            mClipRect.bottom = bottom;
+            mSourceView.invalidateOutline();
+        }
+    }
+
+    /** Returns the bottom clip. */
+    public int getClipBottom() {
+        return mClipRect.bottom;
+    }
+
+    public void setOutlineClipBottom(int bottom) {
+        if (bottom != mOutlineClipRect.bottom) {
+            mOutlineClipRect.bottom = bottom;
+            mSourceView.invalidateOutline();
+        }
+    }
+
+    public int getOutlineClipBottom() {
+        return mOutlineClipRect.bottom;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java
new file mode 100644
index 0000000..6c90fe3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java
@@ -0,0 +1,113 @@
+/*
+ * 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.recents.views;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.Pair;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+
+/**
+ * A full screen overlay layer that allows us to draw views from throughout the system on the top
+ * most layer.
+ */
+public class DebugOverlayView extends FrameLayout {
+
+    final static int sCornerRectSize = 50;
+
+    ArrayList<Pair<Rect, Integer>> mRects = new ArrayList<Pair<Rect, Integer>>();
+    Paint mDebugOutline = new Paint();
+    Paint mTmpPaint = new Paint();
+    boolean mEnabled = true;
+
+    public DebugOverlayView(Context context) {
+        super(context);
+        mDebugOutline.setColor(0xFFff0000);
+        mDebugOutline.setStyle(Paint.Style.STROKE);
+        mDebugOutline.setStrokeWidth(8f);
+        setWillNotDraw(false);
+    }
+
+    /** Enables the debug overlay drawing. */
+    public void enable() {
+        mEnabled = true;
+        invalidate();
+    }
+
+    /** Disables the debug overlay drawing. */
+    public void disable() {
+        mEnabled = false;
+        invalidate();
+    }
+
+    /** Clears all debug rects. */
+    public void clear() {
+        mRects.clear();
+    }
+
+    /** Adds a rect to be drawn. */
+    void addRect(Rect r, int color) {
+        mRects.add(new Pair<Rect, Integer>(r, color));
+        invalidate();
+    }
+
+    /** Adds a view's global rect to be drawn. */
+    void addViewRect(View v, int color) {
+        Rect vr = new Rect();
+        v.getGlobalVisibleRect(vr);
+        mRects.add(new Pair<Rect, Integer>(vr, color));
+        invalidate();
+    }
+
+    /** Adds a rect, relative to a given view to be drawn. */
+    void addRectRelativeToView(View v, Rect r, int color) {
+        Rect vr = new Rect();
+        v.getGlobalVisibleRect(vr);
+        r.offsetTo(vr.left, vr.top);
+        mRects.add(new Pair<Rect, Integer>(r, color));
+        invalidate();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        addRect(new Rect(0, 0, sCornerRectSize, sCornerRectSize), 0xFFff0000);
+        addRect(new Rect(getMeasuredWidth() - sCornerRectSize, getMeasuredHeight() - sCornerRectSize,
+                getMeasuredWidth(), getMeasuredHeight()), 0xFFff0000);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mEnabled) {
+            // Draw the outline
+            canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugOutline);
+
+            // Draw the rects
+            int numRects = mRects.size();
+            for (int i = 0; i < numRects; i++) {
+                Pair<Rect, Integer> r = mRects.get(i);
+                mTmpPaint.setColor(r.second);
+                canvas.drawRect(r.first, mTmpPaint);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
index 3adee0ea..4b5c0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents.views;
 
 import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.widget.ImageView;
@@ -27,8 +28,6 @@
  */
 public class FixedSizeImageView extends ImageView {
 
-    int mFixedWidth;
-    int mFixedHeight;
     boolean mAllowRelayout = true;
     boolean mAllowInvalidate = true;
 
@@ -49,13 +48,6 @@
     }
 
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        mFixedWidth = getMeasuredWidth();
-        mFixedHeight = getMeasuredHeight();
-    }
-
-    @Override
     public void requestLayout() {
         if (mAllowRelayout) {
             super.requestLayout();
@@ -71,7 +63,9 @@
 
     @Override
     public void setImageDrawable(Drawable drawable) {
-        if (drawable == null || (mFixedWidth > 0 && mFixedHeight > 0)) {
+        boolean isNullBitmapDrawable = (drawable instanceof BitmapDrawable) &&
+                (((BitmapDrawable) drawable).getBitmap() == null);
+        if (drawable == null || isNullBitmapDrawable) {
             mAllowRelayout = false;
             mAllowInvalidate = false;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
deleted file mode 100644
index 63f59be..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
+++ /dev/null
@@ -1,285 +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.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import com.android.systemui.R;
-import com.android.systemui.recents.RecentsConfiguration;
-
-
-/**
- * The full screen transition view that gets animated down from the full screen into a task
- * thumbnail view.
- */
-public class FullscreenTransitionOverlayView extends FrameLayout {
-
-    /** The FullscreenTransitionOverlayView callbacks */
-    public interface FullScreenTransitionViewCallbacks {
-        void onEnterAnimationComplete();
-    }
-
-    RecentsConfiguration mConfig;
-
-    FullScreenTransitionViewCallbacks mCb;
-
-    ImageView mScreenshotView;
-    Rect mClipRect = new Rect();
-    Paint mLayerPaint = new Paint();
-    PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
-
-    int mDim;
-    int mMaxDim;
-    AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator();
-
-    boolean mIsAnimating;
-    AnimatorSet mEnterAnimation;
-
-    public FullscreenTransitionOverlayView(Context context) {
-        super(context);
-    }
-
-    public FullscreenTransitionOverlayView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr,
-                                           int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mConfig = RecentsConfiguration.getInstance();
-        mMaxDim = mConfig.taskStackMaxDim;
-        setClipTop(getClipTop());
-        setClipBottom(getClipBottom());
-        setDim(getDim());
-        setWillNotDraw(false);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        mScreenshotView = (ImageView) findViewById(R.id.image);
-    }
-
-    /** Sets the callbacks */
-    public void setCallbacks(FullScreenTransitionViewCallbacks cb) {
-        mCb = cb;
-    }
-
-    /** Sets the top clip */
-    public void setClipTop(int clip) {
-        mClipRect.top = clip;
-        setClipBounds(mClipRect);
-    }
-
-    /** Gets the top clip */
-    public int getClipTop() {
-        return mClipRect.top;
-    }
-
-    /** Sets the bottom clip */
-    public void setClipBottom(int clip) {
-        mClipRect.bottom = clip;
-        setClipBounds(mClipRect);
-    }
-
-    /** Gets the top clip */
-    public int getClipBottom() {
-        return mClipRect.bottom;
-    }
-
-    /** Returns the current dim. */
-    public void setDim(int dim) {
-        mDim = dim;
-        /*
-        int inverse = 255 - mDim;
-        mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
-        mLayerPaint.setColorFilter(mDimColorFilter);
-        setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
-        */
-    }
-
-    /** Returns the current dim. */
-    public int getDim() {
-        return mDim;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
-    /** Prepares the screenshot view for the transition into Recents */
-    public void prepareAnimateOnEnterRecents(Bitmap screenshot) {
-        if (!mConfig.launchedFromAppWithScreenshot) return;
-
-        setClipTop(0);
-        setClipBottom(getMeasuredHeight());
-        setDim(0);
-        setTranslationY(0f);
-        setScaleX(1f);
-        setScaleY(1f);
-        setVisibility(mConfig.launchedFromAppWithScreenshot ? View.VISIBLE : View.INVISIBLE);
-        if (screenshot != null) {
-            mScreenshotView.setImageBitmap(screenshot);
-        } else {
-            mScreenshotView.setImageDrawable(null);
-        }
-    }
-
-    /** Resets the transition view */
-    public void reset() {
-        setVisibility(View.GONE);
-        mScreenshotView.setImageDrawable(null);
-    }
-
-    /** Animates this view as it enters recents */
-    public void animateOnEnterRecents(ViewAnimation.TaskViewEnterContext ctx,
-                                      final Runnable postAnimRunnable) {
-        // Cancel the current animation
-        if (mEnterAnimation != null) {
-            mEnterAnimation.removeAllListeners();
-            mEnterAnimation.cancel();
-        }
-
-        // Calculate the bottom clip
-        Rect targetTaskRect = ctx.targetTaskTransform.rect;
-        float scale = (float) targetTaskRect.width() / getMeasuredWidth();
-        float scaleYOffset = ((1f - scale) * getMeasuredHeight()) / 2;
-        float scaledTopInset = (int) (scale * mConfig.systemInsets.top);
-        int translationY = (int) -scaleYOffset + (int) (mConfig.systemInsets.top - scaledTopInset)
-                + targetTaskRect.top;
-        int clipBottom = mConfig.systemInsets.top + (int) (targetTaskRect.height() / scale);
-
-        // Calculate the dim
-        float minScale = TaskStackViewLayoutAlgorithm.StackPeekMinScale;
-        float scaleRange = 1f - minScale;
-        float dim = (1f - ctx.targetTaskTransform.scale) / scaleRange;
-        dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
-        int toDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
-
-        // Enable the HW Layers on the screenshot view
-        mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
-
-        // Compose the animation
-        mEnterAnimation = new AnimatorSet();
-        mEnterAnimation.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                post(new Runnable() {
-                    @Override
-                    public void run() {
-                        // Mark that we are no longer animating
-                        mIsAnimating = false;
-                        // Disable the HW Layers on this view
-                        setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
-                        // Notify any callbacks
-                        mCb.onEnterAnimationComplete();
-                        // Run the given post-anim runnable
-                        postAnimRunnable.run();
-                    }
-                });
-            }
-        });
-        // XXX: Translation y should be negative initially to simulate moving from the top of the screen?
-        mEnterAnimation.setStartDelay(0);
-        mEnterAnimation.setDuration(475);
-        mEnterAnimation.setInterpolator(mConfig.fastOutSlowInInterpolator);
-        mEnterAnimation.playTogether(
-                // ObjectAnimator.ofInt(this, "clipTop", mConfig.systemInsets.top),
-                ObjectAnimator.ofInt(this, "clipBottom", clipBottom),
-                ObjectAnimator.ofInt(this, "dim", toDim),
-                ObjectAnimator.ofFloat(this, "translationY", translationY),
-                ObjectAnimator.ofFloat(this, "scaleX", scale),
-                ObjectAnimator.ofFloat(this, "scaleY", scale)
-        );
-        setClipTop(mConfig.systemInsets.top);
-        mEnterAnimation.start();
-
-        mIsAnimating = true;
-    }
-
-    /** Animates this view back out of Recents if we were in the process of animating in. */
-    public boolean cancelAnimateOnEnterRecents(final Runnable postAnimRunnable) {
-        if (mIsAnimating) {
-            // Cancel the current animation
-            if (mEnterAnimation != null) {
-                mEnterAnimation.removeAllListeners();
-                mEnterAnimation.cancel();
-            }
-
-            // Enable the HW Layers on the screenshot view
-            mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
-
-            // Compose the animation
-            mEnterAnimation = new AnimatorSet();
-            mEnterAnimation.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    post(new Runnable() {
-                        @Override
-                        public void run() {
-                            // Mark that we are no longer animating
-                            mIsAnimating = false;
-                            // Disable the HW Layers on the screenshot view
-                            mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
-                            // Notify any callbacks
-                            mCb.onEnterAnimationComplete();
-                            // Run the given post-anim runnable
-                            postAnimRunnable.run();
-                        }
-                    });
-                }
-            });
-            mEnterAnimation.setDuration(475);
-            mEnterAnimation.setInterpolator(mConfig.fastOutSlowInInterpolator);
-            mEnterAnimation.playTogether(
-                    ObjectAnimator.ofInt(this, "clipTop", 0),
-                    ObjectAnimator.ofInt(this, "clipBottom", getMeasuredHeight()),
-                    ObjectAnimator.ofInt(this, "dim", 0),
-                    ObjectAnimator.ofFloat(this, "translationY", 0f),
-                    ObjectAnimator.ofFloat(this, "scaleX", 1f),
-                    ObjectAnimator.ofFloat(this, "scaleY", 1f)
-            );
-            mEnterAnimation.start();
-
-            return true;
-        }
-        return false;
-    }
-}
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 e1c652e..356841f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -24,10 +24,8 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -41,7 +39,6 @@
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.RecentsPackageMonitor;
 import com.android.systemui.recents.model.RecentsTaskLoader;
-import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 
@@ -64,13 +61,10 @@
 
     RecentsConfiguration mConfig;
     LayoutInflater mInflater;
-    Paint mDebugModePaint;
+    DebugOverlayView mDebugOverlay;
 
-    // The space partitioning root of this container
-    SpaceNode mBSP;
-    // Search bar view
+    ArrayList<TaskStack> mStacks;
     View mSearchBar;
-    // Recents view callbacks
     RecentsViewCallbacks mCb;
 
     public RecentsView(Context context) {
@@ -96,10 +90,13 @@
         mCb = cb;
     }
 
-    /** Set/get the bsp root node */
-    public void setBSP(SpaceNode n) {
-        mBSP = n;
+    /** Sets the debug overlay */
+    public void setDebugOverlay(DebugOverlayView overlay) {
+        mDebugOverlay = overlay;
+    }
 
+    /** Set/get the bsp root node */
+    public void setTaskStacks(ArrayList<TaskStack> stacks) {
         // Remove all TaskStackViews (but leave the search bar)
         int childCount = getChildCount();
         for (int i = childCount - 1; i >= 0; i--) {
@@ -110,21 +107,18 @@
         }
 
         // Create and add all the stacks for this partition of space.
-        ArrayList<TaskStack> stacks = mBSP.getStacks();
-        for (TaskStack stack : stacks) {
+        mStacks = stacks;
+        int numStacks = mStacks.size();
+        for (int i = 0; i < numStacks; i++) {
+            TaskStack stack = mStacks.get(i);
             TaskStackView stackView = new TaskStackView(getContext(), stack);
             stackView.setCallbacks(this);
+            // Enable debug mode drawing
+            if (mConfig.debugModeEnabled) {
+                stackView.setDebugOverlay(mDebugOverlay);
+            }
             addView(stackView);
         }
-
-        // Enable debug mode drawing
-        if (mConfig.debugModeEnabled) {
-            mDebugModePaint = new Paint();
-            mDebugModePaint.setColor(0xFFff0000);
-            mDebugModePaint.setStyle(Paint.Style.STROKE);
-            mDebugModePaint.setStrokeWidth(5f);
-            setWillNotDraw(false);
-        }
     }
 
     /** Launches the focused task from the first stack if possible */
@@ -151,8 +145,8 @@
         return false;
     }
 
-    /** Launches the first task from the first stack if possible */
-    public boolean launchFirstTask() {
+    /** Launches the task that Recents was launched from, if possible */
+    public boolean launchPreviousTask() {
         // Get the first stack view
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -162,20 +156,17 @@
                 TaskStack stack = stackView.mStack;
                 ArrayList<Task> tasks = stack.getTasks();
 
-                // Get the first task in the stack
+                // Find the launch task in the stack
                 if (!tasks.isEmpty()) {
-                    Task task = tasks.get(tasks.size() - 1);
-                    TaskView tv = null;
-
-                    // Try and use the first child task view as the source of the launch animation
-                    if (stackView.getChildCount() > 0) {
-                        TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
-                        if (stv.getTask() == task) {
-                            tv = stv;
+                    int taskCount = tasks.size();
+                    for (int j = 0; j < taskCount; j++) {
+                        if (tasks.get(j).isLaunchTarget) {
+                            Task task = tasks.get(j);
+                            TaskView tv = stackView.getChildViewForTask(task);
+                            onTaskViewClicked(stackView, tv, stack, task, false);
+                            return true;
                         }
                     }
-                    onTaskViewClicked(stackView, tv, stack, task, false);
-                    return true;
                 }
             }
         }
@@ -243,35 +234,31 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = MeasureSpec.getSize(widthMeasureSpec);
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
         // Get the search bar bounds and measure the search bar layout
         if (mSearchBar != null) {
             Rect searchBarSpaceBounds = new Rect();
-            mConfig.getSearchBarBounds(width, height - mConfig.systemInsets.top, searchBarSpaceBounds);
+            mConfig.getSearchBarBounds(width, height, mConfig.systemInsets.top, searchBarSpaceBounds);
             mSearchBar.measure(
                     MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
                     MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
         }
 
-        // We give the full width of the space, not including the right nav bar insets in landscape,
-        // to the stack view, since we want the tasks to render under the search bar in landscape.
-        // In addition, we give it the full height, not including the top inset or search bar space,
-        // since we want the tasks to render under the navigation buttons in portrait.
         Rect taskStackBounds = new Rect();
-        mConfig.getTaskStackBounds(width, height, taskStackBounds);
-        int childWidth = width - mConfig.systemInsets.right;
-        int childHeight = taskStackBounds.height() - mConfig.systemInsets.top;
+        mConfig.getTaskStackBounds(width, height, mConfig.systemInsets.top,
+                mConfig.systemInsets.right, taskStackBounds);
 
-        // Measure each TaskStackView
+        // Measure each TaskStackView with the full width and height of the window since the 
+        // transition view is a child of that stack view
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child != mSearchBar && child.getVisibility() != GONE) {
-                child.measure(MeasureSpec.makeMeasureSpec(childWidth, widthMode),
-                        MeasureSpec.makeMeasureSpec(childHeight, heightMode));
+                TaskStackView tsv = (TaskStackView) child;
+                // Set the insets to be the top/left inset + search bounds
+                tsv.setStackInsetRect(taskStackBounds);
+                tsv.measure(widthMeasureSpec, heightMeasureSpec);
             }
         }
 
@@ -286,49 +273,30 @@
         // Get the search bar bounds so that we lay it out
         if (mSearchBar != null) {
             Rect searchBarSpaceBounds = new Rect();
-            mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
-            mSearchBar.layout(mConfig.systemInsets.left + searchBarSpaceBounds.left,
-                    mConfig.systemInsets.top + searchBarSpaceBounds.top,
-                    mConfig.systemInsets.left + mSearchBar.getMeasuredWidth(),
-                    mConfig.systemInsets.top + mSearchBar.getMeasuredHeight());
+            mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+                    mConfig.systemInsets.top, searchBarSpaceBounds);
+            mSearchBar.layout(searchBarSpaceBounds.left, searchBarSpaceBounds.top,
+                    searchBarSpaceBounds.right, searchBarSpaceBounds.bottom);
         }
 
-        // We offset the stack view by the left inset (if any), but lay it out under the search bar.
-        // In addition, we offset our stack views by the top inset and search bar height, but not
-        // the bottom insets because we want it to render under the navigation buttons.
-        Rect taskStackBounds = new Rect();
-        mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
-        left += mConfig.systemInsets.left;
-        top += mConfig.systemInsets.top + taskStackBounds.top;
-
-        // Layout each child
-        // XXX: Based on the space node for that task view
+        // Layout each TaskStackView with the full width and height of the window since the 
+        // transition view is a child of that stack view
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child != mSearchBar && child.getVisibility() != GONE) {
-                TaskStackView tsv = (TaskStackView) child;
-                child.layout(left, top, left + tsv.getMeasuredWidth(), top + tsv.getMeasuredHeight());
+                child.layout(left, top, left + child.getMeasuredWidth(),
+                        top + child.getMeasuredHeight());
             }
         }
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        // Debug mode drawing
-        if (mConfig.debugModeEnabled) {
-            canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugModePaint);
-        }
-    }
-
-    @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         // Update the configuration with the latest system insets and trigger a relayout
         mConfig.updateSystemInsets(insets.getSystemWindowInsets());
         requestLayout();
-
-        return insets.consumeSystemWindowInsets(false, false, false, true);
+        return insets.consumeSystemWindowInsets();
     }
 
     /** Notifies each task view of the user interaction. */
@@ -365,11 +333,12 @@
 
     /** Unfilters any filtered stacks */
     public boolean unfilterFilteredStacks() {
-        if (mBSP != null) {
+        if (mStacks != null) {
             // Check if there are any filtered stacks and unfilter them before we back out of Recents
             boolean stacksUnfiltered = false;
-            ArrayList<TaskStack> stacks = mBSP.getStacks();
-            for (TaskStack stack : stacks) {
+            int numStacks = mStacks.size();
+            for (int i = 0; i < numStacks; i++) {
+                TaskStack stack = mStacks.get(i);
                 if (stack.hasFilteredTasks()) {
                     stack.unfilterTasks();
                     stacksUnfiltered = true;
@@ -452,8 +421,7 @@
             public void run() {
                 if (task.isActive) {
                     // Bring an active task to the foreground
-                    RecentsTaskLoader.getInstance().getSystemServicesProxy()
-                            .moveTaskToFront(task.key.id, launchOpts);
+                    ssp.moveTaskToFront(task.key.id, launchOpts);
                 } else {
                     // Launch the activity anew with the desired animation
                     Intent i = new Intent(task.key.baseIntent);
@@ -463,15 +431,9 @@
                         i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                     }
                     try {
-                        UserHandle taskUser = new UserHandle(task.userId);
-                        if (launchOpts != null) {
-                            getContext().startActivityAsUser(i, launchOpts.toBundle(), taskUser);
-
-                        } else {
-                            getContext().startActivityAsUser(i, taskUser);
-                            if (lockToTask) {
-                                ssp.lockCurrentTask();
-                            }
+                        ssp.startActivityFromRecents(task.key.id, launchOpts);
+                        if (launchOpts == null && lockToTask) {
+                            ssp.lockCurrentTask();
                         }
                     } catch (ActivityNotFoundException anfe) {
                         Console.logError(getContext(), "Could not start Activity");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index deb9df3..fd636ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -22,6 +22,7 @@
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.util.AttributeSet;
@@ -43,8 +44,6 @@
 
     RecentsConfiguration mConfig;
 
-    Task mTask;
-
     ImageView mDismissButton;
     ImageView mApplicationIcon;
     TextView mActivityDescription;
@@ -52,7 +51,8 @@
     Drawable mLightDismissDrawable;
     Drawable mDarkDismissDrawable;
 
-    Paint mLayerPaint = new Paint();
+    boolean mIsFullscreen;
+
     static Paint sHighlightPaint;
 
     public TaskBarView(Context context) {
@@ -113,11 +113,18 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        // Draw the highlight at the top edge (but put the bottom edge just out of view)
-        float offset = mConfig.taskViewHighlightPx / 2f;
-        float radius = mConfig.taskViewRoundedCornerRadiusPx;
-        canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
-                getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+        if (!mIsFullscreen) {
+            // Draw the highlight at the top edge (but put the bottom edge just out of view)
+            float offset = mConfig.taskViewHighlightPx / 2f;
+            float radius = mConfig.taskViewRoundedCornerRadiusPx;
+            canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
+                    getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+        }
+    }
+
+    /** Sets whether the current task is full screen or not. */
+    void setIsFullscreen(boolean isFullscreen) {
+        mIsFullscreen = isFullscreen;
     }
 
     /** Synchronizes this bar view's properties with the task's transform */
@@ -149,7 +156,6 @@
 
     /** Binds the bar view to the task */
     void rebindToTask(Task t) {
-        mTask = t;
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
         if (t.activityIcon != null) {
@@ -161,7 +167,11 @@
             mActivityDescription.setText(t.activityLabel);
         }
         // Try and apply the system ui tint
-        setBackgroundColor(t.colorPrimary);
+        int existingBgColor = (getBackground() instanceof ColorDrawable) ?
+                ((ColorDrawable) getBackground()).getColor() : 0;
+        if (existingBgColor != t.colorPrimary) {
+            setBackgroundColor(t.colorPrimary);
+        }
         mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
                 mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
         mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
@@ -170,7 +180,6 @@
 
     /** Unbinds the bar view from the task */
     void unbindFromTask() {
-        mTask = null;
         mApplicationIcon.setImageDrawable(null);
     }
 
@@ -247,14 +256,4 @@
             mDismissButton.setAlpha(1f);
         }
     }
-
-    /** Enable the hw layers on this task view */
-    void enableHwLayers() {
-        mDismissButton.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
-    }
-
-    /** Disable the hw layers on this task view */
-    void disableHwLayers() {
-        mDismissButton.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
new file mode 100644
index 0000000..95af1c9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
@@ -0,0 +1,117 @@
+/*
+ * 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.recents.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import com.android.systemui.recents.RecentsConfiguration;
+
+
+/** The task footer view */
+public class TaskFooterView extends FrameLayout {
+
+    interface TaskFooterViewCallbacks {
+        public void onTaskFooterHeightChanged(int height, int maxHeight);
+    }
+
+    RecentsConfiguration mConfig;
+
+    TaskFooterViewCallbacks mCb;
+    int mFooterHeight;
+    int mMaxFooterHeight;
+    ObjectAnimator mFooterAnimator;
+
+    public TaskFooterView(Context context) {
+        this(context, null);
+    }
+
+    public TaskFooterView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskFooterView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TaskFooterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mConfig = RecentsConfiguration.getInstance();
+        mMaxFooterHeight = mConfig.taskViewLockToAppButtonHeight;
+        setFooterHeight(getFooterHeight());
+    }
+
+    /** Sets the callbacks for when the footer height changes. */
+    void setCallbacks(TaskFooterViewCallbacks cb) {
+        mCb = cb;
+        mCb.onTaskFooterHeightChanged(mFooterHeight, mMaxFooterHeight);
+    }
+
+    /** Sets the footer height. */
+    public void setFooterHeight(int footerHeight) {
+        if (footerHeight != mFooterHeight) {
+            mFooterHeight = footerHeight;
+            mCb.onTaskFooterHeightChanged(footerHeight, mMaxFooterHeight);
+        }
+    }
+
+    /** Gets the footer height. */
+    public int getFooterHeight() {
+        return mFooterHeight;
+    }
+
+    /** Animates the footer into and out of view. */
+    void animateFooterVisibility(final boolean visible, int duration) {
+        // Return early if there is no footer
+        if (mMaxFooterHeight <= 0) return;
+        // Return early if we are already in the final state
+        if (!visible && getVisibility() != View.VISIBLE) return;
+        if (visible && getVisibility() == View.VISIBLE) return;
+
+        // Cancel the previous animation
+        if (mFooterAnimator != null) {
+            mFooterAnimator.removeAllListeners();
+            mFooterAnimator.cancel();
+        }
+        int finalHeight = visible ? mMaxFooterHeight : 0;
+        if (duration > 0) {
+            // Make the view visible for the animation
+            if (visible && getVisibility() != View.VISIBLE) {
+                setVisibility(View.VISIBLE);
+            }
+            mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", finalHeight);
+            mFooterAnimator.setDuration(duration);
+            mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+            mFooterAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (!visible) {
+                        setVisibility(View.INVISIBLE);
+                    }
+                }
+            });
+            mFooterAnimator.start();
+        } else {
+            setFooterHeight(finalHeight);
+            setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
+}
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 8b86258..f135e32 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -23,7 +23,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.graphics.Rect;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -73,6 +72,8 @@
     ViewPool<TaskView, Task> mViewPool;
     ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<TaskViewTransform>();
     DozeTrigger mUIDozeTrigger;
+    DebugOverlayView mDebugOverlay;
+    Rect mTaskStackBounds = new Rect();
 
     // The virtual stack scroll that we use for the card layout
     int mStackScroll;
@@ -94,14 +95,20 @@
     int[] mTmpVisibleRange = new int[2];
     Rect mTmpRect = new Rect();
     Rect mTmpRect2 = new Rect();
+    TaskViewTransform mTmpTransform = new TaskViewTransform();
+    HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<Task, TaskView>();
     LayoutInflater mInflater;
 
+    // A convenience runnable to return all views to the pool
     Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
         @Override
         public void run() {
             int childCount = getChildCount();
             for (int i = childCount - 1; i >= 0; i--) {
-                mViewPool.returnViewToPool((TaskView) getChildAt(i));
+                TaskView tv = (TaskView) getChildAt(i);
+                mViewPool.returnViewToPool(tv);
+                // Also hide the view since we don't need it anymore
+                tv.setVisibility(View.INVISIBLE);
             }
         }
     };
@@ -128,33 +135,6 @@
                 }
             }
         });
-        mHwLayersTrigger = new ReferenceCountedTrigger(getContext(), new Runnable() {
-            @Override
-            public void run() {
-                // Enable hw layers on each of the children
-                int childCount = getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    TaskView tv = (TaskView) getChildAt(i);
-                    tv.enableHwLayers();
-                }
-            }
-        }, new Runnable() {
-            @Override
-            public void run() {
-                // Disable hw layers on each of the children
-                int childCount = getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    TaskView tv = (TaskView) getChildAt(i);
-                    tv.disableHwLayers();
-                }
-            }
-        }, new Runnable() {
-            @Override
-            public void run() {
-                new Throwable("Invalid hw layers ref count").printStackTrace();
-                Console.logError(getContext(), "Invalid HW layers ref count");
-            }
-        });
     }
 
     /** Sets the callbacks */
@@ -162,6 +142,11 @@
         mCb = cb;
     }
 
+    /** Sets the debug overlay */
+    public void setDebugOverlay(DebugOverlayView overlay) {
+        mDebugOverlay = overlay;
+    }
+
     /** Requests that the views be synchronized with the model */
     void requestSynchronizeStackViewsWithModel() {
         requestSynchronizeStackViewsWithModel(0);
@@ -179,19 +164,8 @@
         }
     }
 
-    /** Returns a mapping of child view to Task. */
-    HashMap<Task, TaskView> getTaskChildViewMap() {
-        HashMap<Task, TaskView> taskViewMap = new HashMap<Task, TaskView>();
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            TaskView tv = (TaskView) getChildAt(i);
-            taskViewMap.put(tv.getTask(), tv);
-        }
-        return taskViewMap;
-    }
-
     /** Finds the child view given a specific task. */
-    TaskView getChildViewForTask(Task t) {
+    public TaskView getChildViewForTask(Task t) {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             TaskView tv = (TaskView) getChildAt(i);
@@ -210,19 +184,23 @@
     /**
      * Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
      */
-    private void updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
+    private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
                                        ArrayList<Task> tasks,
                                        int stackScroll,
                                        int[] visibleRangeOut,
                                        boolean boundTranslationsToRect) {
-        // XXX: We should be intelligent about where to look for the visible stack range using the
+        // XXX: We should be intelligent about wheee to look for the visible stack range using the
         //      current stack scroll.
+        // XXX: We should log extra cases like the ones below where we don't expect to hit very often
+        // XXX: Print out approximately how many indices we have to go through to find the first visible transform
 
         int taskTransformCount = taskTransforms.size();
         int taskCount = tasks.size();
         int frontMostVisibleIndex = -1;
         int backMostVisibleIndex = -1;
 
+
+
         // We can reuse the task transforms where possible to reduce object allocation
         if (taskTransformCount < taskCount) {
             // If there are less transforms than tasks, then add as many transforms as necessary
@@ -256,13 +234,14 @@
 
             if (boundTranslationsToRect) {
                 transform.translationY = Math.min(transform.translationY,
-                        mStackAlgorithm.mRect.bottom);
+                        mStackAlgorithm.mViewRect.bottom);
             }
         }
         if (visibleRangeOut != null) {
             visibleRangeOut[0] = frontMostVisibleIndex;
             visibleRangeOut[1] = backMostVisibleIndex;
         }
+        return frontMostVisibleIndex != -1 && backMostVisibleIndex != -1;
     }
 
     /**
@@ -280,34 +259,33 @@
     }
 
     /** Synchronizes the views with the model */
-    void synchronizeStackViewsWithModel() {
+    boolean synchronizeStackViewsWithModel() {
         if (mStackViewsDirty) {
             // Get all the task transforms
             ArrayList<Task> tasks = mStack.getTasks();
             int stackScroll = getStackScroll();
             int[] visibleRange = mTmpVisibleRange;
-            updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
-            TaskViewTransform tmpTransform = new TaskViewTransform();
+            boolean isValidVisibleRange = updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
 
             // Return all the invisible children to the pool
-            HashMap<Task, TaskView> taskChildViewMap = getTaskChildViewMap();
+            mTmpTaskViewMap.clear();
             int childCount = getChildCount();
             for (int i = childCount - 1; i >= 0; i--) {
                 TaskView tv = (TaskView) getChildAt(i);
                 Task task = tv.getTask();
                 int taskIndex = mStack.indexOfTask(task);
-                if (taskIndex < visibleRange[1] || taskIndex > visibleRange[0]) {
-                    taskChildViewMap.remove(task);
+                if (visibleRange[1] <= taskIndex && taskIndex <= visibleRange[0]) {
+                    mTmpTaskViewMap.put(task, tv);
+                } else {
                     mViewPool.returnViewToPool(tv);
                 }
             }
 
             // Pick up all the newly visible children and update all the existing children
-            boolean isValidVisibleRange = visibleRange[0] != -1 && visibleRange[1] != -1;
             for (int i = visibleRange[0]; isValidVisibleRange && i >= visibleRange[1]; i--) {
                 Task task = tasks.get(i);
                 TaskViewTransform transform = mCurrentTaskTransforms.get(i);
-                TaskView tv = taskChildViewMap.get(task);
+                TaskView tv = mTmpTaskViewMap.get(task);
                 int taskIndex = mStack.indexOfTask(task);
 
                 if (tv == null) {
@@ -316,23 +294,26 @@
                         // For items in the list, put them in start animating them from the
                         // approriate ends of the list where they are expected to appear
                         if (transform.t < 0) {
-                            tmpTransform = mStackAlgorithm.getStackTransform(tasks.get(0), stackScroll, tmpTransform);
+                            mTmpTransform = mStackAlgorithm.getStackTransform(tasks.get(0), stackScroll, mTmpTransform);
                         } else {
-                            tmpTransform = mStackAlgorithm.getStackTransform(tasks.get(Math.min(tasks.size() - 1, visibleRange[0] + 1)),
-                                    stackScroll, tmpTransform);
+                            int nextTaskStackScroll = mStackAlgorithm.getStackScrollForTaskIndex(task, 1);
+                            mStackAlgorithm.getStackTransform(nextTaskStackScroll, stackScroll, mTmpTransform);
                         }
-                        tv.updateViewPropertiesToTaskTransform(tmpTransform, 0);
+                        tv.updateViewPropertiesToTaskTransform(mTmpTransform, 0);
                     }
                 }
 
-                // Update and animate the task into place
+                // Animate the task into place
                 tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
                         mStackViewsAnimationDuration);
             }
 
+            // Reset the request-synchronize params
             mStackViewsAnimationDuration = 0;
             mStackViewsDirty = false;
+            return true;
         }
+        return false;
     }
 
     /** Updates the clip for each of the task views. */
@@ -368,13 +349,13 @@
                         clipBottom = (mTmpRect.bottom - scaledMaxFooterHeight - mTmpRect2.top);
                     }
                 }
-                tv.setClipFromBottom(clipBottom);
+                tv.getViewBounds().setClipBottom(clipBottom);
             }
-        }
-        if (getChildCount() > 0) {
-            // The front most task should never be clipped
-            TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
-            tv.setClipFromBottom(0);
+            if (getChildCount() > 0) {
+                // The front most task should never be clipped
+                TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
+                tv.getViewBounds().setClipBottom(0);
+            }
         }
     }
 
@@ -384,18 +365,24 @@
             int childCount = getChildCount();
             for (int i = 0; i < childCount; i++) {
                 TaskView tv = (TaskView) getChildAt(i);
-                tv.setClipFromBottom(0);
+                tv.getViewBounds().setClipBottom(0);
             }
         }
         mEnableStackClipping = stackClippingEnabled;
     }
 
+    /** The stack insets to apply to the stack contents */
+    public void setStackInsetRect(Rect r) {
+        mTaskStackBounds.set(r);
+    }
+
     /** Sets the current stack scroll */
     public void setStackScroll(int value) {
         mStackScroll = value;
         mUIDozeTrigger.poke();
         requestSynchronizeStackViewsWithModel();
     }
+
     /** Sets the current stack scroll without synchronizing the stack view with the model */
     public void setStackScrollRaw(int value) {
         mStackScroll = value;
@@ -408,7 +395,7 @@
     /** Computes the initial stack scroll for the stack. */
     int getInitialStackScroll() {
         if (mStack.getTaskCount() > 2) {
-            return mMaxScroll - (int) (mStackAlgorithm.mTaskRect.height() * (3f/4f));
+            return Math.max(mMinScroll, mMaxScroll - (int) (mStackAlgorithm.mTaskRect.height() * (3f/4f)));
         }
         return mMaxScroll;
     }
@@ -423,17 +410,8 @@
         int curScroll = getStackScroll();
         int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
         if (newScroll != curScroll) {
-            // Enable hw layers on the stack
-            addHwLayersRefCount("animateBoundScroll");
-
             // Start a new scroll animation
-            animateScroll(curScroll, newScroll, new Runnable() {
-                @Override
-                public void run() {
-                    // Disable hw layers on the stack
-                    decHwLayersRefCount("animateBoundScroll");
-                }
-            });
+            animateScroll(curScroll, newScroll, null);
         }
         return mScrollAnimator;
     }
@@ -478,8 +456,6 @@
         if (!mScroller.isFinished()) {
             // Abort the scroller
             mScroller.abortAnimation();
-            // And disable hw layers on the stack
-            decHwLayersRefCount("flingScroll");
         }
     }
 
@@ -521,7 +497,7 @@
 
     /** Returns whether the specified scroll is out of bounds */
     boolean isScrollOutOfBounds() {
-        return getScrollAmountOutOfBounds(getStackScroll()) != 0;
+        return getScrollAmountOutOfBounds(mStackScroll) != 0;
     }
 
     /** Updates the min and max virtual scroll bounds */
@@ -603,17 +579,6 @@
         focusTask(mFocusedTaskIndex, true);
     }
 
-    /** Enables the hw layers and increments the hw layer requirement ref count */
-    void addHwLayersRefCount(String reason) {
-        mHwLayersTrigger.increment();
-    }
-
-    /** Decrements the hw layer requirement ref count and disables the hw layers when we don't
-        need them anymore. */
-    void decHwLayersRefCount(String reason) {
-        mHwLayersTrigger.decrement();
-    }
-
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         return mTouchHandler.onInterceptTouchEvent(ev);
@@ -629,34 +594,29 @@
         if (mScroller.computeScrollOffset()) {
             setStackScroll(mScroller.getCurrY());
             invalidate();
-
-            // If we just finished scrolling, then disable the hw layers
-            if (mScroller.isFinished()) {
-                decHwLayersRefCount("finishedFlingScroll");
-            }
         }
     }
 
     @Override
     public void dispatchDraw(Canvas canvas) {
-        synchronizeStackViewsWithModel();
-        clipTaskViews();
+        if (synchronizeStackViewsWithModel()) {
+            clipTaskViews();
+        }
         super.dispatchDraw(canvas);
     }
 
     /** Computes the stack and task rects */
-    public void computeRects(int width, int height, int insetLeft, int insetBottom) {
+    public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds) {
         // Compute the rects in the stack algorithm
-        mStackAlgorithm.computeRects(mStack.getTasks(), width, height, insetLeft, insetBottom);
+        mStackAlgorithm.computeRects(mStack.getTasks(), windowWidth, windowHeight, taskStackBounds);
 
         // Update the scroll bounds
         updateMinMaxScroll(false);
     }
 
     /**
-     * This is called with the size of the space not including the top or right insets, or the
-     * search bar height in portrait (but including the search bar width in landscape, since we want
-     * to draw under it.
+     * This is called with the full window width and height to allow stack view children to 
+     * perform the full screen transition down.
      */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@@ -664,25 +624,43 @@
         int height = MeasureSpec.getSize(heightMeasureSpec);
 
         // Compute our stack/task rects
-        Rect taskStackBounds = new Rect();
-        mConfig.getTaskStackBounds(width, height, taskStackBounds);
-        computeRects(width, height, taskStackBounds.left, mConfig.systemInsets.bottom);
+        Rect taskStackBounds = new Rect(mTaskStackBounds);
+        taskStackBounds.bottom -= mConfig.systemInsets.bottom;
+        computeRects(width, height, taskStackBounds);
 
         // If this is the first layout, then scroll to the front of the stack and synchronize the
-        // stack views immediately
+        // stack views immediately to load all the views
         if (mAwaitingFirstLayout) {
             setStackScrollToInitialState();
             requestSynchronizeStackViewsWithModel();
             synchronizeStackViewsWithModel();
+
+            // Find the first task and mark it as full screen
+            if (mConfig.launchedFromAppWithScreenshot) {
+                int childCount = getChildCount();
+                for (int i = 0; i < childCount; i++) {
+                    TaskView tv = (TaskView) getChildAt(i);
+                    if (tv.getTask().isLaunchTarget) {
+                        tv.setIsFullScreen(true);
+                        break;
+                    }
+                }
+            }
         }
 
-        // Measure each of the children
+        // Measure each of the TaskViews
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            TaskView t = (TaskView) getChildAt(i);
-            t.measure(MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.width(), MeasureSpec.EXACTLY),
+            TaskView tv = (TaskView) getChildAt(i);
+            if (tv.isFullScreenView()) {
+                tv.measure(widthMeasureSpec, heightMeasureSpec);
+            } else {
+                tv.measure(
+                    MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.width(),
+                            MeasureSpec.EXACTLY),
                     MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.height() +
-                            t.getMaxFooterHeight(), MeasureSpec.EXACTLY));
+                            tv.getMaxFooterHeight(), MeasureSpec.EXACTLY));
+            }
         }
 
         setMeasuredDimension(width, height);
@@ -698,54 +676,45 @@
         // Layout each of the children
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            TaskView t = (TaskView) getChildAt(i);
-            t.layout(mStackAlgorithm.mTaskRect.left, mStackAlgorithm.mStackRectSansPeek.top,
-                    mStackAlgorithm.mTaskRect.right, mStackAlgorithm.mStackRectSansPeek.top +
-                    mStackAlgorithm.mTaskRect.height() + t.getMaxFooterHeight());
+            TaskView tv = (TaskView) getChildAt(i);
+            if (tv.isFullScreenView()) {
+                tv.layout(left, top, left + tv.getMeasuredWidth(), top + tv.getMeasuredHeight());
+            } else {
+                tv.layout(mStackAlgorithm.mTaskRect.left, mStackAlgorithm.mTaskRect.top,
+                        mStackAlgorithm.mTaskRect.right, mStackAlgorithm.mTaskRect.bottom +
+                                tv.getMaxFooterHeight());
+            }
         }
 
         if (mAwaitingFirstLayout) {
-            // Mark that we have completely the first layout
             mAwaitingFirstLayout = false;
+            onFirstLayout();
+        }
+    }
 
-            // Find the target task with the specified id
-            ArrayList<Task> tasks = mStack.getTasks();
-            Task targetTask = null;
-            int targetTaskId = mConfig.launchedToTaskId;
-            if (targetTaskId != -1) {
-                int taskCount = tasks.size();
-                for (int i = 0; i < taskCount; i++) {
-                    Task t = tasks.get(i);
-                    if (t.key.id == targetTaskId) {
-                        targetTask = t;
-                        break;
-                    }
-                }
-            }
+    /** Handler for the first layout. */
+    void onFirstLayout() {
+        // Prepare the first view for its enter animation
+        int offscreenY = mStackAlgorithm.mViewRect.bottom -
+                (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mViewRect.top);
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            TaskView tv = (TaskView) getChildAt(i);
+            tv.prepareEnterRecentsAnimation(tv.getTask().isLaunchTarget, offscreenY);
+        }
 
-            // Prepare the first view for its enter animation
-            int offsetTopAlign = -mStackAlgorithm.mTaskRect.top;
-            int offscreenY = mStackAlgorithm.mRect.bottom -
-                    (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mRect.top);
-            for (int i = childCount - 1; i >= 0; i--) {
-                TaskView tv = (TaskView) getChildAt(i);
-                tv.prepareEnterRecentsAnimation(tv.getTask() == targetTask, offsetTopAlign,
-                        offscreenY);
-            }
+        // If the enter animation started already and we haven't completed a layout yet, do the
+        // enter animation now
+        if (mStartEnterAnimationRequestedAfterLayout) {
+            startEnterRecentsAnimation(mStartEnterAnimationContext);
+            mStartEnterAnimationRequestedAfterLayout = false;
+            mStartEnterAnimationContext = null;
+        }
 
-            // If the enter animation started already and we haven't completed a layout yet, do the
-            // enter animation now
-            if (mStartEnterAnimationRequestedAfterLayout) {
-                startEnterRecentsAnimation(mStartEnterAnimationContext);
-                mStartEnterAnimationRequestedAfterLayout = false;
-                mStartEnterAnimationContext = null;
-            }
-
-            // Update the focused task index to be the next item to the top task
-            if (mConfig.launchedWithAltTab) {
-                // When alt-tabbing, we focus the next previous task
-                focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
-            }
+        // Update the focused task index to be the next item to the top task
+        if (mConfig.launchedWithAltTab) {
+            // When alt-tabbing, we focus the next previous task
+            focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
         }
     }
 
@@ -759,30 +728,6 @@
         }
 
         if (mStack.getTaskCount() > 0) {
-            // Find the target task with the specified id
-            ArrayList<Task> tasks = mStack.getTasks();
-            Task targetTask = null;
-            int targetTaskId = mConfig.launchedToTaskId;
-            if (targetTaskId != -1) {
-                int taskCount = tasks.size();
-                for (int i = 0; i < taskCount; i++) {
-                    Task t = tasks.get(i);
-                    if (t.key.id == targetTaskId) {
-                        targetTask = t;
-                        break;
-                    }
-                }
-            }
-
-            // Find the transform for the target task
-            if (targetTask != null) {
-                ctx.targetTaskTransform = new TaskViewTransform();
-                mStackAlgorithm.getStackTransform(targetTask, getStackScroll(), ctx.targetTaskTransform);
-                Rect taskStackBounds = new Rect();
-                mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
-                ctx.targetTaskTransform.rect.offset(taskStackBounds.left, taskStackBounds.top);
-            }
-
             // Animate all the task views into view
             int childCount = getChildCount();
             for (int i = childCount - 1; i >= 0; i--) {
@@ -791,7 +736,7 @@
                 ctx.currentTaskTransform = new TaskViewTransform();
                 ctx.currentStackViewIndex = i;
                 ctx.currentStackViewCount = childCount;
-                ctx.isCurrentTaskLaunchTarget = (task == targetTask);
+                ctx.currentTaskRect = mStackAlgorithm.mTaskRect;
                 mStackAlgorithm.getStackTransform(task, getStackScroll(), ctx.currentTaskTransform);
                 tv.startEnterRecentsAnimation(ctx);
             }
@@ -802,6 +747,11 @@
                 public void run() {
                     // Start dozing
                     mUIDozeTrigger.startDozing();
+                    // Request an update of the task views after the animation in to 
+                    // relayout the fullscreen view back to its normal size
+                    if (mConfig.launchedFromAppWithScreenshot) {
+                        requestSynchronizeStackViewsWithModel();
+                    }
                 }
             });
         }
@@ -810,8 +760,8 @@
     /** Requests this task stacks to start it's exit-recents animation. */
     public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
         // Animate all the task views into view
-        ctx.offscreenTranslationY = mStackAlgorithm.mRect.bottom -
-                (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mRect.top);
+        ctx.offscreenTranslationY = mStackAlgorithm.mViewRect.bottom -
+                (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mViewRect.top);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             TaskView tv = (TaskView) getChildAt(i);
@@ -967,9 +917,6 @@
         // Detach the view from the hierarchy
         detachViewFromParent(tv);
 
-        // Disable HW layers
-        tv.disableHwLayers();
-
         // Reset the view properties
         tv.resetViewProperties();
     }
@@ -1013,11 +960,6 @@
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
         }
-
-        // Enable hw layers on this view if hw layers are enabled on the stack
-        if (mHwLayersTrigger.getCount() > 0) {
-            tv.enableHwLayers();
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 65407a6..7f94a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -17,7 +17,6 @@
 package com.android.systemui.recents.views;
 
 import android.graphics.Rect;
-import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
@@ -30,14 +29,14 @@
 
     // These are all going to change
     static final float StackOverlapPct = 0.65f; // The overlap height relative to the task height
-    static final float StackPeekHeightPct = 0.1f; // The height of the peek space relative to the stack height
+    static final float StackPeekHeightPct = 0.075f; // The height of the peek space relative to the stack height
     static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area
     static final int StackPeekNumCards = 3; // The number of cards we see in the peek space
 
     RecentsConfiguration mConfig;
 
     // The various rects that define the stack view
-    Rect mRect = new Rect();
+    Rect mViewRect = new Rect();
     Rect mStackRect = new Rect();
     Rect mStackRectSansPeek = new Rect();
     Rect mTaskRect = new Rect();
@@ -53,29 +52,21 @@
     }
 
     /** Computes the stack and task rects */
-    public void computeRects(ArrayList<Task> tasks, int width, int height, int insetLeft, int insetBottom) {
+    public void computeRects(ArrayList<Task> tasks, int windowWidth, int windowHeight,
+                             Rect taskStackBounds) {
         // Note: We let the stack view be the full height because we want the cards to go under the
         //       navigation bar if possible.  However, the stack rects which we use to calculate
         //       max scroll, etc. need to take the nav bar into account
 
         // Compute the stack rects
-        mRect.set(0, 0, width, height);
-        mStackRect.set(mRect);
-        mStackRect.left += insetLeft;
-        mStackRect.bottom -= insetBottom;
+        mViewRect.set(0, 0, windowWidth, windowHeight);
+        mStackRect.set(taskStackBounds);
 
         int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width());
         int heightPadding = mConfig.taskStackTopPaddingPx;
-        if (Constants.DebugFlags.App.EnableSearchLayout) {
-            mStackRect.top += heightPadding;
-            mStackRect.left += widthPadding;
-            mStackRect.right -= widthPadding;
-            mStackRect.bottom -= heightPadding;
-        } else {
-            mStackRect.inset(widthPadding, heightPadding);
-        }
+        mStackRect.inset(widthPadding, heightPadding);
         mStackRectSansPeek.set(mStackRect);
-        mStackRectSansPeek.top += StackPeekHeightPct * mStackRect.height();
+        mStackRectSansPeek.top += StackPeekHeightPct * windowHeight;
 
         // Compute the task rect
         int size = mStackRect.width();
@@ -91,7 +82,7 @@
         // Compute the min and max scroll values
         int numTasks = Math.max(1, tasks.size());
         int taskHeight = mTaskRect.height();
-        int stackHeight = mStackRectSansPeek.height();
+        int stackHeight = mStackRect.height();
 
         if (numTasks <= 1) {
             // If there is only one task, then center the task in the stack rect (sans peek)
@@ -112,12 +103,16 @@
             transformOut.reset();
             return transformOut;
         }
+        return getStackTransform(getStackScrollForTaskIndex(task), stackScroll, transformOut);
+    }
 
+    /** Update/get the transform */
+    public TaskViewTransform getStackTransform(int taskStackScroll, int stackScroll, TaskViewTransform transformOut) {
         // Map the items to an continuous position relative to the specified scroll
         int numPeekCards = StackPeekNumCards;
         float overlapHeight = StackOverlapPct * mTaskRect.height();
         float peekHeight = StackPeekHeightPct * mStackRect.height();
-        float t = (getStackScrollForTaskIndex(task) - stackScroll) / overlapHeight;
+        float t = (taskStackScroll - stackScroll) / overlapHeight;
         float boundedT = Math.max(t, -(numPeekCards + 1));
 
         // Set the scale relative to its position
@@ -125,8 +120,8 @@
         float minScale = StackPeekMinScale;
         float scaleRange = 1f - minScale;
         float scaleInc = scaleRange / (numPeekCards + numFrontScaledCards);
-        float scale = Math.max(minScale, Math.min(1f, minScale + 
-            ((boundedT + (numPeekCards + 1)) * scaleInc)));
+        float scale = Math.max(minScale, Math.min(1f, minScale +
+                ((boundedT + (numPeekCards + 1)) * scaleInc)));
         float scaleYOffset = ((1f - scale) * mTaskRect.height()) / 2;
         // Account for the bar offsets being scaled?
         float scaleBarYOffset = (1f - scale) * mConfig.taskBarHeight;
@@ -156,7 +151,7 @@
         } else {
             transformOut.rect.offset(0, transformOut.translationY);
             Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
-            transformOut.visible = Rect.intersects(mRect, transformOut.rect);
+            transformOut.visible = Rect.intersects(mViewRect, transformOut.rect);
         }
         transformOut.t = t;
         return transformOut;
@@ -178,6 +173,14 @@
     }
 
     /**
+     * Returns the scroll to such that the task transform at that task + index will have t=0.
+     * (If the scroll is not bounded)
+     */
+    int getStackScrollForTaskIndex(Task t, int relativeIndexOffset) {
+        return mTaskOffsetMap.get(t.key) + (int) (relativeIndexOffset * getTaskOverlapHeight());
+    }
+
+    /**
      * Updates the cache of tasks to offsets.
      */
     void updateTaskOffsets(ArrayList<Task> tasks) {
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 191dc37..b83f9cc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -148,8 +148,6 @@
                     if (parent != null) {
                         parent.requestDisallowInterceptTouchEvent(true);
                     }
-                    // Enable HW layers
-                    mSv.addHwLayersRefCount("stackScroll");
                 }
 
                 mLastMotionX = x;
@@ -160,10 +158,6 @@
             case MotionEvent.ACTION_UP: {
                 // Animate the scroll back if we've cancelled
                 mSv.animateBoundScroll();
-                // Disable HW layers
-                if (mIsScrolling) {
-                    mSv.decHwLayersRefCount("stackScroll");
-                }
                 // Reset the drag state and the velocity tracker
                 mIsScrolling = false;
                 mActivePointerId = INACTIVE_POINTER_ID;
@@ -241,8 +235,6 @@
                         if (parent != null) {
                             parent.requestDisallowInterceptTouchEvent(true);
                         }
-                        // Enable HW layers
-                        mSv.addHwLayersRefCount("stackScroll");
                     }
                 }
                 if (mIsScrolling) {
@@ -271,8 +263,6 @@
                 int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
 
                 if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
-                    // Enable HW layers on the stack
-                    mSv.addHwLayersRefCount("flingScroll");
                     // XXX: Make this animation a function of the velocity AND distance
                     int overscrollRange = (int) (Math.min(1f,
                             Math.abs((float) velocity / mMaximumVelocity)) *
@@ -291,10 +281,6 @@
                     mSv.animateBoundScroll();
                 }
 
-                if (mIsScrolling) {
-                    // Disable HW layers
-                    mSv.decHwLayersRefCount("stackScroll");
-                }
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mIsScrolling = false;
                 mTotalScrollMotion = 0;
@@ -315,10 +301,6 @@
                 break;
             }
             case MotionEvent.ACTION_CANCEL: {
-                if (mIsScrolling) {
-                    // Disable HW layers
-                    mSv.decHwLayersRefCount("stackScroll");
-                }
                 if (mSv.isScrollOutOfBounds()) {
                     // Animate the scroll back into bounds
                     // XXX: Make this animation a function of the velocity OR distance
@@ -351,8 +333,6 @@
         TaskView tv = (TaskView) v;
         // Disable clipping with the stack while we are swiping
         tv.setClipViewInStack(false);
-        // Enable HW layers on that task
-        tv.enableHwLayers();
         // Disallow touch events from this task view
         tv.setTouchEnabled(false);
         // Hide the footer
@@ -372,10 +352,6 @@
     @Override
     public void onChildDismissed(View v) {
         TaskView tv = (TaskView) v;
-        // Disable HW layers on that task
-        if (mSv.mHwLayersTrigger.getCount() == 0) {
-            tv.disableHwLayers();
-        }
         // Re-enable clipping with the stack (we will reuse this view)
         tv.setClipViewInStack(true);
         // Re-enable touch events from this task view
@@ -387,10 +363,6 @@
     @Override
     public void onSnapBackCompleted(View v) {
         TaskView tv = (TaskView) v;
-        // Disable HW layers on that task
-        if (mSv.mHwLayersTrigger.getCount() == 0) {
-            tv.disableHwLayers();
-        }
         // Re-enable clipping with the stack
         tv.setClipViewInStack(true);
         // Re-enable touch events from this task view
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
index 08a25f1..1116d51 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
@@ -17,7 +17,7 @@
 package com.android.systemui.recents.views;
 
 import android.content.Context;
-import android.graphics.Canvas;
+import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
@@ -27,11 +27,8 @@
 /** The task thumbnail view */
 public class TaskThumbnailView extends FixedSizeImageView {
 
-    Task mTask;
-
     // Task bar clipping
-    Rect mClipRect;
-    boolean mClipTaskBar = true;
+    Rect mClipRect = new Rect();
 
     public TaskThumbnailView(Context context) {
         this(context, null);
@@ -50,40 +47,51 @@
         setScaleType(ScaleType.FIT_XY);
     }
 
-    @Override
-    public void draw(Canvas canvas) {
-        if (mClipTaskBar && (mClipRect != null)) {
-            int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
-            canvas.clipRect(mClipRect);
-            super.draw(canvas);
-            canvas.restoreToCount(restoreCount);
-        } else {
-            super.draw(canvas);
-        }
+    /** Updates the clip rect based on the given task bar. */
+    void enableTaskBarClip(View taskBar) {
+        int top = (int) Math.max(0, taskBar.getTranslationY() +
+                taskBar.getMeasuredHeight() - 1);
+        mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
+        setClipBounds(mClipRect);
     }
 
-    /** Updates the clip rect based on the given task bar. */
-    void updateTaskBarClip(View taskBar) {
-        // If mClipTaskBar is unset first, then we don't bother setting mTaskBar
-        if (mClipTaskBar) {
-            int top = (int) Math.max(0, taskBar.getTranslationY() +
-                    taskBar.getMeasuredHeight() - 1);
-            mClipRect = new Rect(0, top, getMeasuredWidth(), getMeasuredHeight());
-            invalidate(0, 0, taskBar.getMeasuredWidth(), taskBar.getMeasuredHeight() + 1);
-        }
+    /** Convenience method to enable task bar clipping as a runnable. */
+    Runnable enableTaskBarClipAsRunnable(final View taskBar) {
+        return new Runnable() {
+            @Override
+            public void run() {
+                enableTaskBarClip(taskBar);
+            }
+        };
     }
 
     /** Disables the task bar clipping. */
-    void disableClipTaskBarView() {
-        mClipTaskBar = false;
-        if (mClipRect != null) {
-            invalidate(0, 0, mClipRect.width(), mClipRect.top);
+    Runnable disableTaskBarClipAsRunnable() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+                setClipBounds(mClipRect);
+            }
+        };
+    }
+
+    /** Binds the thumbnail view to the screenshot. */
+    boolean bindToScreenshot(Bitmap ss) {
+        if (ss != null) {
+            setImageBitmap(ss);
+            return true;
         }
+        return false;
+    }
+
+    /** Unbinds the thumbnail view from the screenshot. */
+    void unbindFromScreenshot() {
+        setImageBitmap(null);
     }
 
     /** Binds the thumbnail view to the task */
     void rebindToTask(Task t) {
-        mTask = t;
         if (t.thumbnail != null) {
             setImageBitmap(t.thumbnail);
         }
@@ -91,7 +99,6 @@
 
     /** Unbinds the thumbnail view from the task */
     void unbindFromTask() {
-        mTask = null;
         setImageDrawable(null);
     }
 }
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 4757c5f..259706b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -22,24 +22,24 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.Outline;
+import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.ViewPropertyAnimator;
 import android.view.animation.AccelerateInterpolator;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
+import com.android.systemui.recents.AlternateRecentsComponent;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.model.Task;
 
-
 /* A task view */
-public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.OnClickListener,
-        View.OnLongClickListener {
+public class TaskView extends FrameLayout implements Task.TaskCallbacks,
+        TaskFooterView.TaskFooterViewCallbacks, View.OnClickListener, View.OnLongClickListener {
     /** The TaskView callbacks */
     interface TaskViewCallbacks {
         public void onTaskViewAppIconClicked(TaskView tv);
@@ -51,25 +51,23 @@
 
     RecentsConfiguration mConfig;
 
-    int mFooterHeight;
-    int mMaxFooterHeight;
-    ObjectAnimator mFooterAnimator;
-
     int mDim;
     int mMaxDim;
     AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator();
+    PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
 
     Task mTask;
     boolean mTaskDataLoaded;
     boolean mIsFocused;
+    boolean mIsFullScreenView;
     boolean mIsStub;
     boolean mClipViewInStack;
-    int mClipFromBottom;
+    AnimateableViewBounds mViewBounds;
     Paint mLayerPaint = new Paint();
 
     TaskThumbnailView mThumbnailView;
     TaskBarView mBarView;
-    View mLockToAppButtonView;
+    TaskFooterView mFooterView;
     TaskViewCallbacks mCb;
 
     // Optimizations
@@ -80,18 +78,6 @@
                     updateDimOverlayFromScale();
                 }
             };
-    Runnable mEnableThumbnailClip = new Runnable() {
-        @Override
-        public void run() {
-            mThumbnailView.updateTaskBarClip(mBarView);
-        }
-    };
-    Runnable mDisableThumbnailClip = new Runnable() {
-        @Override
-        public void run() {
-            mThumbnailView.disableClipTaskBarView();
-        }
-    };
 
 
     public TaskView(Context context) {
@@ -109,55 +95,11 @@
     public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
         mConfig = RecentsConfiguration.getInstance();
-        mMaxFooterHeight = mConfig.taskViewLockToAppButtonHeight;
-        setWillNotDraw(false);
-        setClipToOutline(true);
-        setDim(getDim());
-        setFooterHeight(getFooterHeight());
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                // The current height is measured with the footer, so account for the footer height
-                // and the current clip (in the stack)
-                int height = getMeasuredHeight() - mClipFromBottom - mMaxFooterHeight + mFooterHeight;
-                outline.setRoundRect(0, 0, getWidth(), height,
-                        mConfig.taskViewRoundedCornerRadiusPx);
-            }
-        });
-    }
-
-    @Override
-    protected void onFinishInflate() {
         mMaxDim = mConfig.taskStackMaxDim;
-
-        // By default, all views are clipped to other views in their stack
         mClipViewInStack = true;
-
-        // Bind the views
-        mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
-        mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
-        mLockToAppButtonView = findViewById(R.id.lock_to_app);
-
-        if (mTaskDataLoaded) {
-            onTaskDataLoaded();
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        int height = MeasureSpec.getSize(heightMeasureSpec);
-
-        // Measure the bar view, thumbnail, and lock-to-app buttons
-        mBarView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
-        mLockToAppButtonView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(mConfig.taskViewLockToAppButtonHeight,
-                        MeasureSpec.EXACTLY));
-        // Measure the thumbnail height to be the same as the width
-        mThumbnailView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
-        setMeasuredDimension(width, height);
+        mViewBounds = new AnimateableViewBounds(this, mConfig.taskViewRoundedCornerRadiusPx);
+        setOutlineProvider(mViewBounds);
+        setDim(getDim());
     }
 
     /** Set callback */
@@ -170,74 +112,67 @@
         return mTask;
     }
 
+    /** Returns the view bounds. */
+    AnimateableViewBounds getViewBounds() {
+        return mViewBounds;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        // Bind the views
+        mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
+        mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
+        mFooterView = (TaskFooterView) findViewById(R.id.lock_to_app);
+        mFooterView.setCallbacks(this);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        int height = MeasureSpec.getSize(heightMeasureSpec);
+
+        // Measure the bar view, thumbnail, and footer
+        mBarView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
+        mFooterView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(mConfig.taskViewLockToAppButtonHeight,
+                        MeasureSpec.EXACTLY));
+        if (mIsFullScreenView) {
+            // Measure the thumbnail height to be the full dimensions
+            mThumbnailView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+        } else {
+            // Measure the thumbnail to be square
+            mThumbnailView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
+        }
+        setMeasuredDimension(width, height);
+    }
+
     /** Synchronizes this view's properties with the task's transform */
     void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration) {
         // Update the bar view
         mBarView.updateViewPropertiesToTaskTransform(toTransform, duration);
 
-        // Check to see if any properties have changed, and update the task view
-        if (duration > 0) {
-            ViewPropertyAnimator anim = animate();
-            boolean useLayers = false;
-
-            // Animate to the final state
-            if (toTransform.hasTranslationYChangedFrom(getTranslationY())) {
-                anim.translationY(toTransform.translationY);
-            }
-            if (Constants.DebugFlags.App.EnableShadows &&
-                    toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
-                anim.translationZ(toTransform.translationZ);
-            }
-            if (toTransform.hasScaleChangedFrom(getScaleX())) {
-                anim.scaleX(toTransform.scale)
-                    .scaleY(toTransform.scale)
-                    .setUpdateListener(mUpdateDimListener);
-                useLayers = true;
-            }
-            if (toTransform.hasAlphaChangedFrom(getAlpha())) {
-                // Use layers if we animate alpha
-                anim.alpha(toTransform.alpha);
-                useLayers = true;
-            }
-            if (useLayers) {
-                anim.withLayer();
-            }
-            anim.setStartDelay(toTransform.startDelay)
-                .setDuration(duration)
-                .setInterpolator(mConfig.fastOutSlowInInterpolator)
-                .start();
-        } else {
-            // Set the changed properties
-            if (toTransform.hasTranslationYChangedFrom(getTranslationY())) {
-                setTranslationY(toTransform.translationY);
-            }
+        // If we are a full screen view, then only update the Z to keep it in order
+        // XXX: Also update/animate the dim as well
+        if (mIsFullScreenView) {
             if (Constants.DebugFlags.App.EnableShadows &&
                     toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
                 setTranslationZ(toTransform.translationZ);
             }
-            if (toTransform.hasScaleChangedFrom(getScaleX())) {
-                setScaleX(toTransform.scale);
-                setScaleY(toTransform.scale);
-                updateDimOverlayFromScale();
-            }
-            if (toTransform.hasAlphaChangedFrom(getAlpha())) {
-                setAlpha(toTransform.alpha);
-            }
+            return;
         }
+
+        // Apply the transform
+        toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
+                mUpdateDimListener);
     }
 
     /** Resets this view's properties */
     void resetViewProperties() {
-        setTranslationX(0f);
-        setTranslationY(0f);
-        if (Constants.DebugFlags.App.EnableShadows) {
-            setTranslationZ(0f);
-        }
-        setScaleX(1f);
-        setScaleY(1f);
-        setAlpha(1f);
         setDim(0);
-        invalidate();
+        TaskViewTransform.reset(this);
     }
 
     /**
@@ -262,20 +197,13 @@
 
     /** Prepares this task view for the enter-recents animations.  This is called earlier in the
      * first layout because the actual animation into recents may take a long time. */
-    public void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, int offsetY,
-                                             int offscreenY) {
+    public void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, int offscreenY) {
         if (mConfig.launchedFromAppWithScreenshot) {
             if (isTaskViewLaunchTargetTask) {
-                // Hide the task view as we are going to animate the full screenshot into view
-                // and then replace it with this view once we are done
-                setVisibility(View.INVISIBLE);
                 // Also hide the front most task bar view so we can animate it in
                 mBarView.prepareEnterRecentsAnimation();
             } else {
-                // Top align the task views
-                setTranslationY(offsetY);
-                setScaleX(1f);
-                setScaleY(1f);
+                // Don't do anything for the side views
             }
 
         } else if (mConfig.launchedFromAppWithThumbnail) {
@@ -300,49 +228,56 @@
     /** Animates this task view as it enters recents */
     public void startEnterRecentsAnimation(final ViewAnimation.TaskViewEnterContext ctx) {
         TaskViewTransform transform = ctx.currentTaskTransform;
+        Rect taskRect = ctx.currentTaskRect;
 
         if (mConfig.launchedFromAppWithScreenshot) {
-            if (ctx.isCurrentTaskLaunchTarget) {
-                // Animate the full screenshot down first, before swapping with this task view
-                ctx.fullScreenshotView.animateOnEnterRecents(ctx, new Runnable() {
-                    @Override
-                    public void run() {
-                        // Animate the task bar of the first task view
-                        mBarView.startEnterRecentsAnimation(0, mEnableThumbnailClip);
-                        setVisibility(View.VISIBLE);
-                        // Animate the footer into view
-                        animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
-                        // Decrement the post animation trigger
-                        ctx.postAnimationTrigger.decrement();
-                    }
-                });
-            } else {
-                // Animate the tasks down behind the full screenshot
-                animate()
-                        .scaleX(transform.scale)
-                        .scaleY(transform.scale)
-                        .translationY(transform.translationY)
-                        .setStartDelay(0)
-                        .setUpdateListener(null)
-                        .setInterpolator(mConfig.linearOutSlowInInterpolator)
-                        .setDuration(475)
-                        .withLayer()
+            if (mTask.isLaunchTarget) {
+                // XXX: We would have to animate the trasnlationY of the task view bar along with the clip and
+                // reset it at the bottom
+
+                // XXX: This should actually be the inset on the current app...
+                mViewBounds.animateClipTop(taskRect.top, mConfig.taskViewEnterFromHomeDuration * 5);
+                mViewBounds.animateClipBottom(getMeasuredHeight() - taskRect.bottom, mConfig.taskViewEnterFromHomeDuration * 5);
+
+                animate().scaleX(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
+                        .scaleY(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
+                        .translationY(taskRect.top + transform.translationY)
+                        .setDuration(mConfig.taskViewEnterFromHomeDuration * 5)
                         .withEndAction(new Runnable() {
                             @Override
                             public void run() {
-                                mEnableThumbnailClip.run();
+                                // Animate the task bar of the first task view
+                                mBarView.startEnterRecentsAnimation(0, mThumbnailView.enableTaskBarClipAsRunnable(mBarView));
+                                // Animate the footer into view (if it is the front most task)
+                                animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
                                 // Decrement the post animation trigger
                                 ctx.postAnimationTrigger.decrement();
+
+                                // XXX Request layout and only start hte next animation after the next
+                                // layout
+
+                                setIsFullScreen(false);
+                                mThumbnailView.unbindFromScreenshot();
+
+                                // Recycle the full screen screenshot
+                                AlternateRecentsComponent.consumeLastScreenshot();
                             }
                         })
                         .start();
+            } else {
+                // Otherwise, just enable the thumbnail clip
+                mThumbnailView.enableTaskBarClip(mBarView);
+
+                // Animate the footer into view
+                animateFooterVisibility(true, 0);
             }
             ctx.postAnimationTrigger.increment();
 
         } else if (mConfig.launchedFromAppWithThumbnail) {
-            if (ctx.isCurrentTaskLaunchTarget) {
+            if (mTask.isLaunchTarget) {
                 // Animate the task bar of the first task view
-                mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay, mEnableThumbnailClip);
+                mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+                        mThumbnailView.enableTaskBarClipAsRunnable(mBarView));
 
                 // Animate the dim into view as well
                 ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimOverlayFromScale());
@@ -360,10 +295,9 @@
                 ctx.postAnimationTrigger.increment();
 
                 // Animate the footer into view
-                animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration
-                );
+                animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
             } else {
-                mEnableThumbnailClip.run();
+                mThumbnailView.enableTaskBarClip(mBarView);
             }
 
         } else if (mConfig.launchedFromHome) {
@@ -382,11 +316,10 @@
                     .setUpdateListener(null)
                     .setInterpolator(mConfig.quintOutInterpolator)
                     .setDuration(mConfig.taskViewEnterFromHomeDuration)
-                    .withLayer()
                     .withEndAction(new Runnable() {
                         @Override
                         public void run() {
-                            mEnableThumbnailClip.run();
+                            mThumbnailView.enableTaskBarClip(mBarView);
                             // Decrement the post animation trigger
                             ctx.postAnimationTrigger.decrement();
                         }
@@ -395,11 +328,11 @@
             ctx.postAnimationTrigger.increment();
 
             // Animate the footer into view
-            animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration
-            );
+            animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration);
+
         } else {
             // Otherwise, just enable the thumbnail clip
-            mEnableThumbnailClip.run();
+            mThumbnailView.enableTaskBarClip(mBarView);
 
             // Animate the footer into view
             animateFooterVisibility(true, 0);
@@ -414,7 +347,6 @@
                 .setUpdateListener(null)
                 .setInterpolator(mConfig.fastOutLinearInInterpolator)
                 .setDuration(mConfig.taskViewExitToHomeDuration)
-                .withLayer()
                 .withEndAction(ctx.postAnimationTrigger.decrementAsRunnable())
                 .start();
         ctx.postAnimationTrigger.increment();
@@ -424,7 +356,7 @@
     public void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask) {
         if (isLaunchingTask) {
             // Disable the thumbnail clip and animate the bar out
-            mBarView.startLaunchTaskAnimation(mDisableThumbnailClip, r);
+            mBarView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
 
             // Animate the dim
             if (mDim > 0) {
@@ -450,7 +382,6 @@
             .setUpdateListener(null)
             .setInterpolator(mConfig.fastOutSlowInInterpolator)
             .setDuration(mConfig.taskViewRemoveAnimDuration)
-            .withLayer()
             .withEndAction(new Runnable() {
                 @Override
                 public void run() {
@@ -478,32 +409,23 @@
         mBarView.setNoUserInteractionState();
     }
 
-    /** Enable the hw layers on this task view */
-    void enableHwLayers() {
-        mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
-        mBarView.enableHwLayers();
-        mLockToAppButtonView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+    /** Sets whether this task view is full screen or not. */
+    void setIsFullScreen(boolean isFullscreen) {
+        mIsFullScreenView = isFullscreen;
+        mBarView.setIsFullscreen(isFullscreen);
+        if (isFullscreen) {
+            // If we are full screen, then disable the bottom outline clip for the footer
+            mViewBounds.setOutlineClipBottom(0);
+        }
     }
 
-    /** Disable the hw layers on this task view */
-    void disableHwLayers() {
-        mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
-        mBarView.disableHwLayers();
-        mLockToAppButtonView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+    /** Returns whether this task view should currently be drawn as a full screen view. */
+    boolean isFullScreenView() {
+        return mIsFullScreenView;
     }
 
     /** Sets the stubbed state of this task view. */
     void setStubState(boolean isStub) {
-        if (!mIsStub && isStub) {
-            // This is now a stub task view, so clip to the bar height, hide the thumbnail
-            setClipBounds(new Rect(0, 0, getMeasuredWidth(), mBarView.getMeasuredHeight()));
-            mThumbnailView.setVisibility(View.INVISIBLE);
-            // Temporary
-            mBarView.mActivityDescription.setText("Stub");
-        } else if (mIsStub && !isStub) {
-            setClipBounds(null);
-            mThumbnailView.setVisibility(View.VISIBLE);
-        }
         mIsStub = isStub;
     }
 
@@ -512,7 +434,7 @@
      * view.
      */
     boolean shouldClipViewInStack() {
-        return mClipViewInStack && (getVisibility() == View.VISIBLE);
+        return mClipViewInStack && !mIsFullScreenView && (getVisibility() == View.VISIBLE);
     }
 
     /** Sets whether this view should be clipped, or clipped against. */
@@ -523,81 +445,28 @@
         }
     }
 
-    void setClipFromBottom(int clipFromBottom) {
-        clipFromBottom = Math.max(0, Math.min(getMeasuredHeight(), clipFromBottom));
-        if (mClipFromBottom != clipFromBottom) {
-            mClipFromBottom = clipFromBottom;
-            invalidateOutline();
-        }
-    }
-
-    /** Sets the footer height. */
-    public void setFooterHeight(int footerHeight) {
-        if (footerHeight != mFooterHeight) {
-            mFooterHeight = footerHeight;
-            invalidateOutline();
-            invalidate(0, getMeasuredHeight() - mMaxFooterHeight, getMeasuredWidth(),
-                    getMeasuredHeight());
-        }
-    }
-
-    /** Gets the footer height. */
-    public int getFooterHeight() {
-        return mFooterHeight;
-    }
-
     /** Gets the max footer height. */
     public int getMaxFooterHeight() {
-        return mMaxFooterHeight;
+        return mFooterView.mMaxFooterHeight;
     }
 
     /** Animates the footer into and out of view. */
-    public void animateFooterVisibility(boolean visible, int duration) {
-        if (!mTask.lockToThisTask) {
-            if (mLockToAppButtonView.getVisibility() == View.VISIBLE) {
-                mLockToAppButtonView.setVisibility(View.INVISIBLE);
-            }
-            return;
-        }
-        if (mMaxFooterHeight <= 0) return;
-
-        if (mFooterAnimator != null) {
-            mFooterAnimator.removeAllListeners();
-            mFooterAnimator.cancel();
-        }
-        int height = visible ? mMaxFooterHeight : 0;
-        if (visible && mLockToAppButtonView.getVisibility() != View.VISIBLE) {
-            if (duration > 0) {
-                setFooterHeight(0);
-            } else {
-                setFooterHeight(mMaxFooterHeight);
-            }
-            mLockToAppButtonView.setVisibility(View.VISIBLE);
-        }
-        if (duration > 0) {
-            mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", height);
-            mFooterAnimator.setDuration(duration);
-            mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
-            if (!visible) {
-                mFooterAnimator.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        mLockToAppButtonView.setVisibility(View.INVISIBLE);
-                    }
-                });
-            }
-            mFooterAnimator.start();
-        } else {
-            if (!visible) {
-                mLockToAppButtonView.setVisibility(View.INVISIBLE);
-            }
-        }
+    void animateFooterVisibility(boolean visible, int duration) {
+        // Hide the footer if we are a full screen view
+        if (mIsFullScreenView) return;
+        // Hide the footer if the current task can not be locked to
+        if (!mTask.lockToTaskEnabled || !mTask.lockToThisTask) return;
+        // Otherwise, animate the visibility
+        mFooterView.animateFooterVisibility(visible, duration);
     }
 
     /** Returns the current dim. */
     public void setDim(int dim) {
         mDim = dim;
-        postInvalidateOnAnimation();
+        int inverse = 255 - mDim;
+        mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
+        mLayerPaint.setColorFilter(mDimColorFilter);
+        setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
     }
 
     /** Returns the current dim. */
@@ -619,25 +488,19 @@
         setDim(getDimOverlayFromScale());
     }
 
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
-        // Apply the dim if necessary
-        if (mDim > 0) {
-            canvas.drawColor(mDim << 24);
-        }
-    }
+    /**** View drawing ****/
 
     @Override
     protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
-        if (mIsStub && (child == mThumbnailView)) {
+        if (mIsStub && (child != mBarView)) {
             // Skip the thumbnail view if we are in stub mode
             return false;
         }
         return super.drawChild(canvas, child, drawingTime);
     }
 
+    /**** View focus state ****/
+
     /**
      * Sets the focused task explicitly. We need a separate flag because requestFocus() won't happen
      * if the view is not currently visible, or we are in touch state (where we still want to keep
@@ -691,14 +554,18 @@
     public void onTaskDataLoaded() {
         if (mThumbnailView != null && mBarView != null) {
             // Bind each of the views to the new task data
-            mThumbnailView.rebindToTask(mTask);
+            if (mIsFullScreenView) {
+                mThumbnailView.bindToScreenshot(AlternateRecentsComponent.getLastScreenshot());
+            } else {
+                mThumbnailView.rebindToTask(mTask);
+            }
             mBarView.rebindToTask(mTask);
             // Rebind any listeners
             if (Constants.DebugFlags.App.EnableTaskFiltering) {
                 mBarView.mApplicationIcon.setOnClickListener(this);
             }
             mBarView.mDismissButton.setOnClickListener(this);
-            mLockToAppButtonView.setOnClickListener(this);
+            mFooterView.setOnClickListener(this);
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
                 if (mConfig.developerOptionsEnabled) {
                     mBarView.mApplicationIcon.setOnLongClickListener(this);
@@ -720,7 +587,7 @@
                 mBarView.mApplicationIcon.setOnClickListener(null);
             }
             mBarView.mDismissButton.setOnClickListener(null);
-            mLockToAppButtonView.setOnClickListener(null);
+            mFooterView.setOnClickListener(null);
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
                 mBarView.mApplicationIcon.setOnLongClickListener(null);
             }
@@ -733,8 +600,23 @@
         setOnClickListener(enabled ? this : null);
     }
 
+    /**** TaskFooterView.TaskFooterViewCallbacks ****/
+
     @Override
-    public void onClick(final View v) {
+    public void onTaskFooterHeightChanged(int height, int maxHeight) {
+        if (mIsFullScreenView) {
+            // Disable the bottom outline clip when fullscreen
+            mViewBounds.setOutlineClipBottom(0);
+        } else {
+            // Update the bottom clip in our outline provider
+            mViewBounds.setOutlineClipBottom(maxHeight - height);
+        }
+    }
+
+    /**** View.OnClickListener Implementation ****/
+
+    @Override
+     public void onClick(final View v) {
         // We purposely post the handler delayed to allow for the touch feedback to draw
         final TaskView tv = this;
         postDelayed(new Runnable() {
@@ -752,13 +634,15 @@
                     });
                     // Hide the footer
                     tv.animateFooterVisibility(false, mConfig.taskViewRemoveAnimDuration);
-                } else if (v == tv || v == mLockToAppButtonView) {
-                    mCb.onTaskViewClicked(tv, tv.getTask(), (v == mLockToAppButtonView));
+                } else if (v == tv || v == mFooterView) {
+                    mCb.onTaskViewClicked(tv, tv.getTask(), (v == mFooterView));
                 }
             }
         }, 125);
     }
 
+    /**** View.OnLongClickListener Implementation ****/
+
     @Override
     public boolean onLongClick(View v) {
         if (v == mBarView.mApplicationIcon) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index b351b03..aeb4fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -16,7 +16,12 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.ValueAnimator;
 import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.animation.Interpolator;
+import com.android.systemui.recents.Constants;
 
 
 /* The transform state for a task view */
@@ -77,6 +82,72 @@
         return (Float.compare(translationZ, v) != 0);
     }
 
+    /** Applies this transform to a view. */
+    public void applyToTaskView(View v, int duration, Interpolator interp, boolean allowLayers,
+                                ValueAnimator.AnimatorUpdateListener scaleUpdateListener) {
+        // Check to see if any properties have changed, and update the task view
+        if (duration > 0) {
+            ViewPropertyAnimator anim = v.animate();
+            boolean requiresLayers = false;
+
+            // Animate to the final state
+            if (hasTranslationYChangedFrom(v.getTranslationY())) {
+                anim.translationY(translationY);
+            }
+            if (Constants.DebugFlags.App.EnableShadows &&
+                    hasTranslationZChangedFrom(v.getTranslationZ())) {
+                anim.translationZ(translationZ);
+            }
+            if (hasScaleChangedFrom(v.getScaleX())) {
+                anim.scaleX(scale)
+                    .scaleY(scale)
+                    .setUpdateListener(scaleUpdateListener);
+                requiresLayers = true;
+            }
+            if (hasAlphaChangedFrom(v.getAlpha())) {
+                // Use layers if we animate alpha
+                anim.alpha(alpha);
+                requiresLayers = true;
+            }
+            if (requiresLayers && allowLayers) {
+                anim.withLayer();
+            }
+            anim.setStartDelay(startDelay)
+                    .setDuration(duration)
+                    .setInterpolator(interp)
+                    .start();
+        } else {
+            // Set the changed properties
+            if (hasTranslationYChangedFrom(v.getTranslationY())) {
+                v.setTranslationY(translationY);
+            }
+            if (Constants.DebugFlags.App.EnableShadows &&
+                    hasTranslationZChangedFrom(v.getTranslationZ())) {
+                v.setTranslationZ(translationZ);
+            }
+            if (hasScaleChangedFrom(v.getScaleX())) {
+                v.setScaleX(scale);
+                v.setScaleY(scale);
+                scaleUpdateListener.onAnimationUpdate(null);
+            }
+            if (hasAlphaChangedFrom(v.getAlpha())) {
+                v.setAlpha(alpha);
+            }
+        }
+    }
+
+    /** Reset the transform on a view. */
+    public static void reset(View v) {
+        v.setTranslationX(0f);
+        v.setTranslationY(0f);
+        if (Constants.DebugFlags.App.EnableShadows) {
+            v.setTranslationZ(0f);
+        }
+        v.setScaleX(1f);
+        v.setScaleY(1f);
+        v.setAlpha(1f);
+    }
+
     @Override
     public String toString() {
         return "TaskViewTransform delay: " + startDelay + " y: " + translationY + " z: " + translationZ +
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
index e50a5cf..3705cb5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.views;
 
+import android.graphics.Rect;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 
 /* Common code related to view animations */
@@ -23,27 +24,22 @@
 
     /* The animation context for a task view animation into Recents */
     public static class TaskViewEnterContext {
-        // The full screenshot view that we are animating down
-        FullscreenTransitionOverlayView fullScreenshotView;
-        // The transform of the target task view that we are animating into
-        TaskViewTransform targetTaskTransform;
         // A trigger to run some logic when all the animations complete.  This works around the fact
         // that it is difficult to coordinate ViewPropertyAnimators
         ReferenceCountedTrigger postAnimationTrigger;
 
         // These following properties are updated for each task view we start the enter animation on
 
+        // The task rect for the current stack
+        Rect currentTaskRect;
         // The transform of the current task view
         TaskViewTransform currentTaskTransform;
-        // Whether this is the front most task view
-        boolean isCurrentTaskLaunchTarget;
         // The view index of the current task view
         int currentStackViewIndex;
         // The total number of task views
         int currentStackViewCount;
 
-        public TaskViewEnterContext(FullscreenTransitionOverlayView fss, ReferenceCountedTrigger t) {
-            fullScreenshotView = fss;
+        public TaskViewEnterContext(ReferenceCountedTrigger t) {
             postAnimationTrigger = t;
         }
     }
@@ -53,6 +49,7 @@
         // A trigger to run some logic when all the animations complete.  This works around the fact
         // that it is difficult to coordinate ViewPropertyAnimators
         ReferenceCountedTrigger postAnimationTrigger;
+
         // The translationY to apply to a TaskView to move it off the bottom of the task stack
         int offscreenTranslationY;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index a41ec22..303454b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -44,6 +44,7 @@
     public static final int MODE_TRANSLUCENT = 2;
     public static final int MODE_LIGHTS_OUT = 3;
     public static final int MODE_TRANSPARENT = 4;
+    public static final int MODE_WARNING = 5;
 
     public static final int LIGHTS_IN_DURATION = 250;
     public static final int LIGHTS_OUT_DURATION = 750;
@@ -100,6 +101,7 @@
         if (mode == MODE_TRANSLUCENT) return "MODE_TRANSLUCENT";
         if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT";
         if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
+        if (mode == MODE_WARNING) return "MODE_WARNING";
         throw new IllegalArgumentException("Unknown mode " + mode);
     }
 
@@ -115,6 +117,7 @@
         private final int mOpaque;
         private final int mSemiTransparent;
         private final int mTransparent;
+        private final int mWarning;
         private final Drawable mGradient;
         private final TimeInterpolator mInterpolator;
 
@@ -135,10 +138,12 @@
                 mOpaque = 0xff0000ff;
                 mSemiTransparent = 0x7f0000ff;
                 mTransparent = 0x2f0000ff;
+                mWarning = 0xffff0000;
             } else {
                 mOpaque = res.getColor(R.color.system_bar_background_opaque);
                 mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent);
                 mTransparent = res.getColor(R.color.system_bar_background_transparent);
+                mWarning = res.getColor(R.color.system_bar_background_warning);
             }
             mGradient = res.getDrawable(gradientResourceId);
             mInterpolator = new LinearInterpolator();
@@ -189,7 +194,9 @@
         @Override
         public void draw(Canvas canvas) {
             int targetGradientAlpha = 0, targetColor = 0;
-            if (mMode == MODE_TRANSLUCENT) {
+            if (mMode == MODE_WARNING) {
+                targetColor = mWarning;
+            } else if (mMode == MODE_TRANSLUCENT) {
                 targetColor = mSemiTransparent;
             } else if (mMode == MODE_SEMI_TRANSPARENT) {
                 targetColor = mSemiTransparent;
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 b5f38ae..74bc698 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -38,6 +38,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.FlashlightController;
 
 /**
  * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
@@ -63,6 +64,7 @@
     private ActivityStarter mActivityStarter;
     private UnlockMethodCache mUnlockMethodCache;
     private LockPatternUtils mLockPatternUtils;
+    private FlashlightController mFlashlightController;
 
     public KeyguardBottomAreaView(Context context) {
         super(context);
@@ -102,6 +104,10 @@
         mActivityStarter = activityStarter;
     }
 
+    public void setFlashlightController(FlashlightController flashlightController) {
+        mFlashlightController = flashlightController;
+    }
+
     private Intent getCameraIntent() {
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
         boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
@@ -189,6 +195,7 @@
     }
 
     public void launchCamera() {
+        mFlashlightController.killFlashlight();
         Intent intent = getCameraIntent();
         if (intent == SECURE_CAMERA_INTENT) {
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
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 86bb202..e4e67c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -28,6 +28,7 @@
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -126,11 +127,14 @@
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
 import com.android.systemui.statusbar.policy.CastControllerImpl;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.HotspotControllerImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.LocationControllerImpl;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -204,6 +208,7 @@
     BatteryController mBatteryController;
     LocationControllerImpl mLocationController;
     NetworkControllerImpl mNetworkController;
+    HotspotControllerImpl mHotspotController;
     RotationLockControllerImpl mRotationLockController;
     UserInfoController mUserInfoController;
     ZenModeController mZenModeController;
@@ -212,6 +217,7 @@
     KeyguardUserSwitcher mKeyguardUserSwitcher;
     FlashlightController mFlashlightController;
     UserSwitcherController mUserSwitcherController;
+    KeyguardMonitor mKeyguardMonitor;
 
     int mNaturalBarHeight = -1;
     int mIconSize = -1;
@@ -702,7 +708,18 @@
         // Other icons
         mLocationController = new LocationControllerImpl(mContext); // will post a notification
         mBatteryController = new BatteryController(mContext);
+        mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
+            @Override
+            public void onPowerSaveChanged() {
+                mHandler.post(mCheckBarModes);
+            }
+            @Override
+            public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+                // noop
+            }
+        });
         mNetworkController = new NetworkControllerImpl(mContext);
+        mHotspotController = new HotspotControllerImpl(mContext);
         mBluetoothController = new BluetoothControllerImpl(mContext);
         if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
             mRotationLockController = new RotationLockControllerImpl(mContext);
@@ -748,16 +765,18 @@
         }
 
         mFlashlightController = new FlashlightController(mContext);
+        mKeyguardBottomArea.setFlashlightController(mFlashlightController);
         mUserSwitcherController = new UserSwitcherController(mContext);
+        mKeyguardMonitor = new KeyguardMonitor();
 
         // Set up the quick settings tile panel
         mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
         if (mQSPanel != null) {
             final QSTileHost qsh = new QSTileHost(mContext, this,
                     mBluetoothController, mLocationController, mRotationLockController,
-                    mNetworkController, mZenModeController, null /*tethering*/,
-                    mCastController, mVolumeComponent, mFlashlightController,
-                    mUserSwitcherController);
+                    mNetworkController, mZenModeController, mHotspotController,
+                    mCastController, mFlashlightController,
+                    mUserSwitcherController, mKeyguardMonitor);
             mQSPanel.setHost(qsh);
             for (QSTile<?> tile : qsh.getTiles()) {
                 mQSPanel.addTile(tile);
@@ -2304,7 +2323,12 @@
     }
 
     private void checkBarMode(int mode, int windowState, BarTransitions transitions) {
-        final boolean anim = (mScreenOn == null || mScreenOn) && windowState != WINDOW_STATE_HIDDEN;
+        final boolean powerSave = mBatteryController.isPowerSave();
+        final boolean anim = (mScreenOn == null || mScreenOn) && windowState != WINDOW_STATE_HIDDEN
+                && !powerSave;
+        if (powerSave && getBarState() != StatusBarState.KEYGUARD) {
+            mode = MODE_WARNING;
+        }
         transitions.transitionTo(mode, anim);
     }
 
@@ -2319,7 +2343,8 @@
         @Override
         public void run() {
             checkBarModes();
-        }};
+        }
+    };
 
     @Override
     public void setInteracting(int barWindow, boolean interacting) {
@@ -2638,6 +2663,9 @@
         if (mUserSwitcherController != null) {
             mUserSwitcherController.dump(fd, pw, args);
         }
+        if (mBatteryController != null) {
+            mBatteryController.dump(fd, pw, args);
+        }
     }
 
     private String hunStateToString(Entry entry) {
@@ -3105,6 +3133,8 @@
             int barMode = "opaque".equals(mode) ? MODE_OPAQUE :
                     "translucent".equals(mode) ? MODE_TRANSLUCENT :
                     "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT :
+                    "transparent".equals(mode) ? MODE_TRANSPARENT :
+                    "warning".equals(mode) ? MODE_WARNING :
                     -1;
             if (barMode != -1) {
                 boolean animate = true;
@@ -3207,6 +3237,8 @@
         checkBarModes();
         updateCarrierLabelVisibility(false);
         updateMediaMetaData(false);
+        mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
+                mStatusBarKeyguardViewManager.isSecure());
     }
 
     private void updateDozingState() {
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 a599070..c2fd24c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -36,13 +36,13 @@
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.volume.VolumeComponent;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -57,21 +57,21 @@
     private final RotationLockController mRotation;
     private final NetworkController mNetwork;
     private final ZenModeController mZen;
-    private final TetheringController mTethering;
+    private final HotspotController mHotspot;
     private final CastController mCast;
     private final Looper mLooper;
     private final CurrentUserTracker mUserTracker;
-    private final VolumeComponent mVolume;
     private final ArrayList<QSTile<?>> mTiles = new ArrayList<QSTile<?>>();
     private final FlashlightController mFlashlight;
     private final UserSwitcherController mUserSwitcherController;
+    private final KeyguardMonitor mKeyguard;
 
     public QSTileHost(Context context, PhoneStatusBar statusBar,
             BluetoothController bluetooth, LocationController location,
             RotationLockController rotation, NetworkController network,
-            ZenModeController zen, TetheringController tethering,
-            CastController cast, VolumeComponent volume, FlashlightController flashlight,
-            UserSwitcherController userSwitcher) {
+            ZenModeController zen, HotspotController hotspot,
+            CastController cast, FlashlightController flashlight,
+            UserSwitcherController userSwitcher, KeyguardMonitor keyguard) {
         mContext = context;
         mStatusBar = statusBar;
         mBluetooth = bluetooth;
@@ -79,11 +79,11 @@
         mRotation = rotation;
         mNetwork = network;
         mZen = zen;
-        mTethering = tethering;
+        mHotspot = hotspot;
         mCast = cast;
-        mVolume = volume;
         mFlashlight = flashlight;
         mUserSwitcherController = userSwitcher;
+        mKeyguard = keyguard;
 
         final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName());
         ht.start();
@@ -95,10 +95,10 @@
         mTiles.add(new CellularTile(this));
         mTiles.add(new AirplaneModeTile(this));
         mTiles.add(new RotationLockTile(this));
+        mTiles.add(new FlashlightTile(this));
         mTiles.add(new LocationTile(this));
         mTiles.add(new CastTile(this));
         mTiles.add(new HotspotTile(this));
-        mTiles.add(new FlashlightTile(this));
 
         mUserTracker = new CurrentUserTracker(mContext) {
             @Override
@@ -167,8 +167,8 @@
     }
 
     @Override
-    public TetheringController getTetheringController() {
-        return mTethering;
+    public HotspotController getHotspotController() {
+        return mHotspot;
     }
 
     @Override
@@ -177,13 +177,13 @@
     }
 
     @Override
-    public VolumeComponent getVolumeComponent() {
-        return mVolume;
+    public FlashlightController getFlashlightController() {
+        return mFlashlight;
     }
 
     @Override
-    public FlashlightController getFlashlightController() {
-        return mFlashlight;
+    public KeyguardMonitor getKeyguardMonitor() {
+        return mKeyguard;
     }
 
     public UserSwitcherController getUserSwitcherController() {
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 b2709bc..2f88e21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -99,6 +99,7 @@
     private QSPanel mQSPanel;
 
     private final Rect mClipBounds = new Rect();
+    private final StatusIconClipper mStatusIconClipper = new StatusIconClipper();
 
     public StatusBarHeaderView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -231,6 +232,7 @@
             updateAvatarScale();
             updateClockLp();
             updateBatteryLevelPaddingEnd();
+            mStatusIconClipper.update();
         }
     }
 
@@ -363,6 +365,11 @@
         }
     }
 
+    @Override
+    public void onPowerSaveChanged() {
+        // could not care less
+    }
+
     private void updateClickTargets() {
         setClickable(!mKeyguardShowing || mExpanded);
         mDateTime.setClickable(mExpanded);
@@ -440,7 +447,7 @@
         mSystemIconsContainer.addView(systemIcons);
         mStatusIcons = systemIcons.findViewById(R.id.statusIcons);
         mSignalCluster = systemIcons.findViewById(R.id.signal_cluster);
-        mSignalCluster.addOnLayoutChangeListener(mSignalClusterChanged);
+        mSignalCluster.addOnLayoutChangeListener(mStatusIconClipper);
     }
 
     public void onSystemIconsDetached() {
@@ -448,7 +455,7 @@
             mStatusIcons.setVisibility(View.VISIBLE);
         }
         if (mSignalCluster != null) {
-            mSignalCluster.removeOnLayoutChangeListener(mSignalClusterChanged);
+            mSignalCluster.removeOnLayoutChangeListener(mStatusIconClipper);
             mSignalCluster.setVisibility(View.VISIBLE);
         }
         mStatusIcons = null;
@@ -465,6 +472,7 @@
         updateMultiUserSwitch();
         updateClickTargets();
         updateBatteryLevelPaddingEnd();
+        mStatusIconClipper.update();
     }
 
     public void setUserInfoController(UserInfoController userInfoController) {
@@ -531,7 +539,7 @@
         // here.
     }
 
-    private final OnLayoutChangeListener mSignalClusterChanged = new OnLayoutChangeListener() {
+    private final class StatusIconClipper implements OnLayoutChangeListener {
         private final Rect mClipBounds = new Rect();
 
         @Override
@@ -541,9 +549,14 @@
             // they are mirrored to the real status bar.
             mClipBounds.set(left, 0, mSystemIconsContainer.getWidth(),
                     mSystemIconsContainer.getHeight());
-            mSystemIconsContainer.setClipBounds(mClipBounds);
+            update();
         }
-    };
+
+        public void update() {
+            final boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
+            mSystemIconsContainer.setClipBounds(onKeyguardAndCollapsed ? null : mClipBounds);
+        }
+    }
 
     private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index ccfe18d..1e65543 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -16,41 +16,49 @@
 
 package com.android.systemui.statusbar.policy;
 
-import com.android.internal.app.IBatteryStats;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarHeaderView;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.BatteryManager;
-import android.os.BatteryStats;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.text.format.Formatter;
+import android.os.PowerManager;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 public class BatteryController extends BroadcastReceiver {
-    private static final String TAG = "StatusBar.BatteryController";
+    private static final String TAG = "BatteryController";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+    private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+    private final PowerManager mPowerManager;
 
     private int mLevel;
     private boolean mPluggedIn;
     private boolean mCharging;
     private boolean mCharged;
-
-    public interface BatteryStateChangeCallback {
-        public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
-    }
+    private boolean mPowerSave;
 
     public BatteryController(Context context) {
+        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
         context.registerReceiver(this, filter);
+
+        updatePowerSave();
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("BatteryController state:");
+        pw.print("  mLevel="); pw.println(mLevel);
+        pw.print("  mPluggedIn="); pw.println(mPluggedIn);
+        pw.print("  mCharging="); pw.println(mCharging);
+        pw.print("  mCharged="); pw.println(mCharged);
+        pw.print("  mPowerSave="); pw.println(mPowerSave);
     }
 
     public void addStateChangedCallback(BatteryStateChangeCallback cb) {
@@ -75,9 +83,40 @@
             mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
             mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
 
-            for (BatteryStateChangeCallback cb : mChangeCallbacks) {
-                cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
-            }
+            fireBatteryLevelChanged();
+        } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
+            updatePowerSave();
         }
     }
+
+    public boolean isPowerSave() {
+        return mPowerSave;
+    }
+
+    private void updatePowerSave() {
+        final boolean powerSave = mPowerManager.isPowerSaveMode();
+        if (powerSave == mPowerSave) return;
+        mPowerSave = powerSave;
+        if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
+        firePowerSaveChanged();
+    }
+
+    private void fireBatteryLevelChanged() {
+        final int N = mChangeCallbacks.size();
+        for (int i = 0; i < N; i++) {
+            mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+        }
+    }
+
+    private void firePowerSaveChanged() {
+        final int N = mChangeCallbacks.size();
+        for (int i = 0; i < N; i++) {
+            mChangeCallbacks.get(i).onPowerSaveChanged();
+        }
+    }
+
+    public interface BatteryStateChangeCallback {
+        void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
+        void onPowerSaveChanged();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index b059043..e05e34b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Size;
 import android.view.Surface;
@@ -41,6 +42,14 @@
 public class FlashlightController {
 
     private static final String TAG = "FlashlightController";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private static final boolean ENFORCE_AVAILABILITY_LISTENER =
+            SystemProperties.getBoolean("persist.sysui.flash.listener", false);
+
+    private static final int DISPATCH_ERROR = 0;
+    private static final int DISPATCH_OFF = 1;
+    private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
 
     private final CameraManager mCameraManager;
     /** Call {@link #ensureHandler()} before using */
@@ -52,6 +61,8 @@
     /** Lock on {@code this} when accessing */
     private boolean mFlashlightEnabled;
 
+    private String mCameraId;
+    private boolean mCameraAvailable;
     private CameraDevice mCameraDevice;
     private CaptureRequest mFlashlightRequest;
     private CameraCaptureSession mSession;
@@ -60,6 +71,20 @@
 
     public FlashlightController(Context mContext) {
         mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+        initialize();
+    }
+
+    public void initialize() {
+        try {
+            mCameraId = getCameraId();
+        } catch (CameraAccessException e) {
+            Log.e(TAG, "Couldn't initialize.", e);
+            return;
+        }
+
+        ensureHandler();
+        mCameraAvailable = true;
+        mCameraManager.addAvailabilityListener(mAvailabilityListener, mHandler);
     }
 
     public synchronized void setFlashlight(boolean enabled) {
@@ -69,12 +94,18 @@
         }
     }
 
-    public boolean isAvailable() {
-        try {
-            return getCameraId() != null;
-        } catch (CameraAccessException e) {
-            return false;
+    public void killFlashlight() {
+        boolean enabled;
+        synchronized (this) {
+            enabled = mFlashlightEnabled;
         }
+        if (enabled) {
+            mHandler.post(mKillFlashlightRunnable);
+        }
+    }
+
+    public synchronized boolean isAvailable() {
+        return ENFORCE_AVAILABILITY_LISTENER ? mCameraAvailable : (mCameraId != null);
     }
 
     public void addListener(FlashlightListener l) {
@@ -207,24 +238,30 @@
     }
 
     private void dispatchOff() {
-        dispatchListeners(false, true /* off */);
+        dispatchListeners(DISPATCH_OFF, false /* argument (ignored) */);
     }
 
     private void dispatchError() {
-        dispatchListeners(true /* error */, false);
+        dispatchListeners(DISPATCH_ERROR, false /* argument (ignored) */);
     }
 
-    private void dispatchListeners(boolean error, boolean off) {
+    private void dispatchAvailabilityChanged(boolean available) {
+        dispatchListeners(DISPATCH_AVAILABILITY_CHANGED, available);
+    }
+
+    private void dispatchListeners(int message, boolean argument) {
         synchronized (mListeners) {
             final int N = mListeners.size();
             boolean cleanup = false;
             for (int i = 0; i < N; i++) {
                 FlashlightListener l = mListeners.get(i).get();
                 if (l != null) {
-                    if (error) {
+                    if (message == DISPATCH_ERROR) {
                         l.onFlashlightError();
-                    } else if (off) {
+                    } else if (message == DISPATCH_OFF) {
                         l.onFlashlightOff();
+                    } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
+                        l.onFlashlightAvailabilityChanged(argument);
                     }
                 } else {
                     cleanup = true;
@@ -293,6 +330,48 @@
         }
     };
 
+    private final Runnable mKillFlashlightRunnable = new Runnable() {
+        @Override
+        public void run() {
+            synchronized (this) {
+                mFlashlightEnabled = false;
+            }
+            updateFlashlight(true /* forceDisable */);
+            dispatchOff();
+        }
+    };
+
+    private final CameraManager.AvailabilityListener mAvailabilityListener =
+            new CameraManager.AvailabilityListener() {
+        @Override
+        public void onCameraAvailable(String cameraId) {
+            if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
+            if (cameraId.equals(mCameraId)) {
+                setCameraAvailable(true);
+            }
+        }
+
+        @Override
+        public void onCameraUnavailable(String cameraId) {
+            if (DEBUG) Log.d(TAG, "onCameraUnavailable(" + cameraId + ")");
+            if (cameraId.equals(mCameraId)) {
+                setCameraAvailable(false);
+            }
+        }
+
+        private void setCameraAvailable(boolean available) {
+            boolean changed;
+            synchronized (FlashlightController.this) {
+                changed = mCameraAvailable != available;
+                mCameraAvailable = available;
+            }
+            if (changed) {
+                if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
+                dispatchAvailabilityChanged(available);
+            }
+        }
+    };
+
     public interface FlashlightListener {
 
         /**
@@ -304,5 +383,11 @@
          * Called when there is an error that turns the flashlight off.
          */
         void onFlashlightError();
+
+        /**
+         * Called when there is a change in availability of the flashlight functionality
+         * @param available true if the flashlight is currently available.
+         */
+        void onFlashlightAvailabilityChanged(boolean available);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TetheringController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/TetheringController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 143ebaa..7ca91a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TetheringController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -16,13 +16,14 @@
 
 package com.android.systemui.statusbar.policy;
 
-public interface TetheringController {
+public interface HotspotController {
     void addCallback(Callback callback);
     void removeCallback(Callback callback);
     boolean isHotspotEnabled();
     boolean isHotspotSupported();
+    void setHotspotEnabled(boolean enabled);
 
     public interface Callback {
-        void onHotspotChanged(boolean hotspot);
+        void onHotspotChanged(boolean enabled);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
new file mode 100644
index 0000000..eea8396
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -0,0 +1,108 @@
+/*
+ * 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.statusbar.policy;
+
+import java.util.ArrayList;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class HotspotControllerImpl implements HotspotController {
+
+    private static final String TAG = "HotspotController";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+    private final Receiver mReceiver = new Receiver();
+    private final Context mContext;
+    private final WifiManager mWifiManager;
+    private final ConnectivityManager mConnectivityManager;
+
+    public HotspotControllerImpl(Context context) {
+        mContext = context;
+        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        mConnectivityManager = (ConnectivityManager)
+                mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+    }
+
+    public void addCallback(Callback callback) {
+        if (callback == null || mCallbacks.contains(callback)) return;
+        if (DEBUG) Log.d(TAG, "addCallback " + callback);
+        mCallbacks.add(callback);
+        mReceiver.setListening(!mCallbacks.isEmpty());
+    }
+
+    public void removeCallback(Callback callback) {
+        if (callback == null) return;
+        if (DEBUG) Log.d(TAG, "removeCallback " + callback);
+        mCallbacks.remove(callback);
+        mReceiver.setListening(!mCallbacks.isEmpty());
+    }
+
+    @Override
+    public boolean isHotspotEnabled() {
+        return mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED;
+    }
+
+    @Override
+    public boolean isHotspotSupported() {
+        final boolean isSecondaryUser = ActivityManager.getCurrentUser() != UserHandle.USER_OWNER;
+        return !isSecondaryUser && mConnectivityManager.isTetheringSupported();
+    }
+
+    @Override
+    public void setHotspotEnabled(boolean enabled) {
+        mWifiManager.setWifiApEnabled(null, enabled);
+    }
+
+    private void fireCallback(boolean isEnabled) {
+        for (Callback callback : mCallbacks) {
+            callback.onHotspotChanged(isEnabled);
+        }
+    }
+
+    private final class Receiver extends BroadcastReceiver {
+        private boolean mRegistered;
+
+        public void setListening(boolean listening) {
+            if (listening && !mRegistered) {
+                if (DEBUG) Log.d(TAG, "Registering receiver");
+                final IntentFilter filter = new IntentFilter();
+                filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+                mContext.registerReceiver(this, filter);
+                mRegistered = true;
+            } else if (!listening && mRegistered) {
+                if (DEBUG) Log.d(TAG, "Unregistering receiver");
+                mContext.unregisterReceiver(this);
+                mRegistered = false;
+            }
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
+            fireCallback(isHotspotEnabled());
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
new file mode 100644
index 0000000..0b3575f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.statusbar.policy;
+
+import java.util.ArrayList;
+
+public final class KeyguardMonitor {
+
+    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+
+    private boolean mShowing;
+    private boolean mSecure;
+
+    public void addCallback(Callback callback) {
+        mCallbacks.add(callback);
+    }
+
+    public void removeCallback(Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    public boolean isShowing() {
+        return mShowing;
+    }
+
+    public boolean isSecure() {
+        return mSecure;
+    }
+
+    public void notifyKeyguardState(boolean showing, boolean secure) {
+        if (mShowing == showing && mSecure == secure) return;
+        mShowing = showing;
+        mSecure = secure;
+        for (Callback callback : mCallbacks) {
+            callback.onKeyguardChanged();
+        }
+    }
+
+    public interface Callback {
+        void onKeyguardChanged();
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 49e7c67..7bf2c34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -66,6 +66,7 @@
 
     private ArrayList<UserRecord> mUsers = new ArrayList<>();
     private Dialog mExitGuestDialog;
+    private int mLastNonGuestUser = UserHandle.USER_OWNER;
 
     public UserSwitcherController(Context context) {
         mContext = context;
@@ -204,7 +205,14 @@
     }
 
     private void exitGuest(int id) {
-        switchToUserId(UserHandle.USER_OWNER);
+        int newId = UserHandle.USER_OWNER;
+        if (mLastNonGuestUser != UserHandle.USER_OWNER) {
+            UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
+            if (info != null && info.isEnabled() && info.supportsSwitchTo()) {
+                newId = info.id;
+            }
+        }
+        switchToUserId(newId);
         mUserManager.removeUser(id);
     }
 
@@ -230,6 +238,9 @@
                     if (record.isCurrent != shouldBeCurrent) {
                         mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
                     }
+                    if (shouldBeCurrent && !record.isGuest) {
+                        mLastNonGuestUser = record.info.id;
+                    }
                 }
                 notifyAdapters();
             }
@@ -244,6 +255,7 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("UserSwitcherController state:");
+        pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
         pw.print("  mUsers.size="); pw.println(mUsers.size());
         for (int i = 0; i < mUsers.size(); i++) {
             final UserRecord u = mUsers.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index ee7206f..fe2733b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -171,7 +171,10 @@
         for (int i = 0; i < childCount; i++) {
             View child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
-            childViewState.belowSpeedBump = speedBumpIndex != -1 && i > speedBumpIndex;
+
+            // The speed bump can also be gone, so equality needs to be taken when comparing
+            // indices.
+            childViewState.belowSpeedBump = speedBumpIndex != -1 && i >= speedBumpIndex;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 7abfc88..f5447a2 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -65,7 +65,6 @@
 
         final AlertController.AlertParams ap = mAlertParams;
         ap.mTitle = getString(R.string.usb_debugging_title);
-        ap.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
         ap.mMessage = getString(R.string.usb_debugging_message, fingerprints);
         ap.mPositiveButtonText = getString(android.R.string.ok);
         ap.mNegativeButtonText = getString(android.R.string.cancel);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 17a5263..56b8c92 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -6409,54 +6409,61 @@
             mIsSystemRestore = isFullSystemRestore;
             mFinished = false;
 
-            if (filterSet == null) {
-                // We want everything and a pony
-                List<PackageInfo> apps
-                        = PackageManagerBackupAgent.getStorableApplications(mPackageManager);
-                filterSet = packagesToNames(apps);
-                if (DEBUG) {
-                    Slog.i(TAG, "Full restore; asking for " + filterSet.length + " apps");
-                }
-            }
-
-            mAcceptSet = new ArrayList<PackageInfo>(filterSet.length);
-
-            // Pro tem, we insist on moving the settings provider package to last place.
-            // Keep track of whether it's in the list, and bump it down if so.  We also
-            // want to do the system package itself first if it's called for.
-            boolean hasSystem = false;
-            boolean hasSettings = false;
-            for (int i = 0; i < filterSet.length; i++) {
-                try {
-                    PackageInfo info = mPackageManager.getPackageInfo(filterSet[i], 0);
-                    if ("android".equals(info.packageName)) {
-                        hasSystem = true;
-                        continue;
+            if (targetPackage != null) {
+                // Single package restore
+                mAcceptSet = new ArrayList<PackageInfo>();
+                mAcceptSet.add(targetPackage);
+            } else {
+                // Everything possible, or a target set
+                if (filterSet == null) {
+                    // We want everything and a pony
+                    List<PackageInfo> apps =
+                            PackageManagerBackupAgent.getStorableApplications(mPackageManager);
+                    filterSet = packagesToNames(apps);
+                    if (DEBUG) {
+                        Slog.i(TAG, "Full restore; asking for " + filterSet.length + " apps");
                     }
-                    if (SETTINGS_PACKAGE.equals(info.packageName)) {
-                        hasSettings = true;
-                        continue;
-                    }
+                }
 
-                    if (appIsEligibleForBackup(info.applicationInfo)) {
-                        mAcceptSet.add(info);
+                mAcceptSet = new ArrayList<PackageInfo>(filterSet.length);
+
+                // Pro tem, we insist on moving the settings provider package to last place.
+                // Keep track of whether it's in the list, and bump it down if so.  We also
+                // want to do the system package itself first if it's called for.
+                boolean hasSystem = false;
+                boolean hasSettings = false;
+                for (int i = 0; i < filterSet.length; i++) {
+                    try {
+                        PackageInfo info = mPackageManager.getPackageInfo(filterSet[i], 0);
+                        if ("android".equals(info.packageName)) {
+                            hasSystem = true;
+                            continue;
+                        }
+                        if (SETTINGS_PACKAGE.equals(info.packageName)) {
+                            hasSettings = true;
+                            continue;
+                        }
+
+                        if (appIsEligibleForBackup(info.applicationInfo)) {
+                            mAcceptSet.add(info);
+                        }
+                    } catch (NameNotFoundException e) {
+                        // requested package name doesn't exist; ignore it
                     }
-                } catch (NameNotFoundException e) {
-                    // requested package name doesn't exist; ignore it
                 }
-            }
-            if (hasSystem) {
-                try {
-                    mAcceptSet.add(0, mPackageManager.getPackageInfo("android", 0));
-                } catch (NameNotFoundException e) {
-                    // won't happen; we know a priori that it's valid
+                if (hasSystem) {
+                    try {
+                        mAcceptSet.add(0, mPackageManager.getPackageInfo("android", 0));
+                    } catch (NameNotFoundException e) {
+                        // won't happen; we know a priori that it's valid
+                    }
                 }
-            }
-            if (hasSettings) {
-                try {
-                    mAcceptSet.add(mPackageManager.getPackageInfo(SETTINGS_PACKAGE, 0));
-                } catch (NameNotFoundException e) {
-                    // this one is always valid too
+                if (hasSettings) {
+                    try {
+                        mAcceptSet.add(mPackageManager.getPackageInfo(SETTINGS_PACKAGE, 0));
+                    } catch (NameNotFoundException e) {
+                        // this one is always valid too
+                    }
                 }
             }
 
@@ -6558,117 +6565,77 @@
         private  void startRestore() {
             sendStartRestore(mAcceptSet.size());
 
-            UnifiedRestoreState nextState = UnifiedRestoreState.RESTORE_FINISHED;
             try {
-                // If we don't yet have PM metadata for this token, synthesize an
-                // entry for the PM pseudopackage and make it the first to be
-                // restored.
                 String transportDir = mTransport.transportDirName();
                 mStateDir = new File(mBaseStateDir, transportDir);
-                File metadataDir = new File(mStateDir, "_metadata");
-                metadataDir.mkdirs();
-                File metadataFile = new File(metadataDir, Long.toHexString(mToken));
-                try {
-                    // PM info is cached in $BASE/transport/_metadata/$TOKEN
-                    mPmAgent = new PackageManagerBackupAgent(metadataFile);
-                } catch (IOException e) {
-                    // Nope, we need to get it via restore
-                    if (MORE_DEBUG) Slog.v(TAG, "Need to restore @pm@");
-                    PackageInfo pmPackage = new PackageInfo();
-                    pmPackage.packageName = PACKAGE_MANAGER_SENTINEL;
-                    mAcceptSet.add(0, pmPackage);
-                }
+
+                // Fetch the current metadata from the dataset first
+                PackageInfo pmPackage = new PackageInfo();
+                pmPackage.packageName = PACKAGE_MANAGER_SENTINEL;
+                mAcceptSet.add(0, pmPackage);
 
                 PackageInfo[] packages = mAcceptSet.toArray(new PackageInfo[0]);
                 mStatus = mTransport.startRestore(mToken, packages);
                 if (mStatus != BackupTransport.TRANSPORT_OK) {
                     Slog.e(TAG, "Transport error " + mStatus + "; no restore possible");
                     mStatus = BackupTransport.TRANSPORT_ERROR;
-                    nextState = UnifiedRestoreState.FINAL;
+                    executeNextState(UnifiedRestoreState.FINAL);
                     return;
                 }
 
-                if (mPmAgent == null) {
-                    if (DEBUG) {
-                        Slog.v(TAG, "Need to fetch metadata for token "
-                                + Long.toHexString(mToken));
-                    }
-                    RestoreDescription desc = mTransport.nextRestorePackage();
-                    if (desc == null) {
-                        Slog.e(TAG, "No restore metadata available; halting");
-                        mStatus = BackupTransport.TRANSPORT_ERROR;
-                        nextState = UnifiedRestoreState.FINAL;
-                        return;
-                    }
-                    if (!PACKAGE_MANAGER_SENTINEL.equals(desc.getPackageName())) {
-                        Slog.e(TAG, "Required metadata but got " + desc.getPackageName());
-                        mStatus = BackupTransport.TRANSPORT_ERROR;
-                        nextState = UnifiedRestoreState.FINAL;
-                        return;
-                    }
-
-                    // Pull the Package Manager metadata from the restore set first
-                    mCurrentPackage = new PackageInfo();
-                    mCurrentPackage.packageName = PACKAGE_MANAGER_SENTINEL;
-                    mPmAgent = new PackageManagerBackupAgent(mPackageManager, null);
-                    mAgent = IBackupAgent.Stub.asInterface(mPmAgent.onBind());
-                    if (MORE_DEBUG) {
-                        Slog.v(TAG, "initiating restore for PMBA");
-                    }
-                    initiateOneRestore(mCurrentPackage, 0);
-                    // The PM agent called operationComplete() already, because our invocation
-                    // of it is process-local and therefore synchronous.  That means that a
-                    // RUNNING_QUEUE message is already enqueued.  Only if we're unable to
-                    // proceed with running the queue do we remove that pending message and
-                    // jump straight to the FINAL state.
-
-                    // Verify that the backup set includes metadata.  If not, we can't do
-                    // signature/version verification etc, so we simply do not proceed with
-                    // the restore operation.
-                    if (!mPmAgent.hasMetadata()) {
-                        Slog.e(TAG, "No restore metadata available, so not restoring settings");
-                        EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                                PACKAGE_MANAGER_SENTINEL,
-                                "Package manager restore metadata missing");
-                        mStatus = BackupTransport.TRANSPORT_ERROR;
-                        mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
-                        nextState = UnifiedRestoreState.FINAL;
-                        return;
-                    }
-
-                    // Success; cache the metadata and continue as expected with the
-                    // RUNNING_QUEUE step already enqueued.
-                    if (DEBUG) {
-                        Slog.v(TAG, "Got metadata; caching and proceeding to restore");
-                    }
-                    try {
-                        mPmAgent.saveToDisk(metadataFile);
-                    } catch (IOException e) {
-                        // Something bad; we need to abort
-                        Slog.e(TAG, "Unable to write restored metadata");
-                        EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                                PACKAGE_MANAGER_SENTINEL,
-                                "Unable to write restored metadata");
-                        mStatus = BackupTransport.TRANSPORT_ERROR;
-                        mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
-                        nextState = UnifiedRestoreState.FINAL;
-                        return;
-                    }
-                } else {
-                    // We have the PMBA already, so we can proceed directly to
-                    // the RUNNING_QUEUE state ourselves.
-                    if (MORE_DEBUG) Slog.v(TAG, "PMBA from cache; proceeding to run queue");
-                    nextState = UnifiedRestoreState.RUNNING_QUEUE;
+                RestoreDescription desc = mTransport.nextRestorePackage();
+                if (desc == null) {
+                    Slog.e(TAG, "No restore metadata available; halting");
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
+                    executeNextState(UnifiedRestoreState.FINAL);
+                    return;
                 }
+                if (!PACKAGE_MANAGER_SENTINEL.equals(desc.getPackageName())) {
+                    Slog.e(TAG, "Required metadata but got " + desc.getPackageName());
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
+                    executeNextState(UnifiedRestoreState.FINAL);
+                    return;
+                }
+
+                // Pull the Package Manager metadata from the restore set first
+                mCurrentPackage = new PackageInfo();
+                mCurrentPackage.packageName = PACKAGE_MANAGER_SENTINEL;
+                mPmAgent = new PackageManagerBackupAgent(mPackageManager, null);
+                mAgent = IBackupAgent.Stub.asInterface(mPmAgent.onBind());
+                if (MORE_DEBUG) {
+                    Slog.v(TAG, "initiating restore for PMBA");
+                }
+                initiateOneRestore(mCurrentPackage, 0);
+                // The PM agent called operationComplete() already, because our invocation
+                // of it is process-local and therefore synchronous.  That means that the
+                // next-state message (RUNNING_QUEUE) is already enqueued.  Only if we're
+                // unable to proceed with running the queue do we remove that pending
+                // message and jump straight to the FINAL state.
+
+                // Verify that the backup set includes metadata.  If not, we can't do
+                // signature/version verification etc, so we simply do not proceed with
+                // the restore operation.
+                if (!mPmAgent.hasMetadata()) {
+                    Slog.e(TAG, "No restore metadata available, so not restoring");
+                    EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
+                            PACKAGE_MANAGER_SENTINEL,
+                            "Package manager restore metadata missing");
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
+                    mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
+                    executeNextState(UnifiedRestoreState.FINAL);
+                    return;
+                }
+
+                // Success; cache the metadata and continue as expected with the
+                // next state already enqueued
+
             } catch (RemoteException e) {
                 // If we lost the transport at any time, halt
                 Slog.e(TAG, "Unable to contact transport for restore");
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
-                nextState = UnifiedRestoreState.FINAL;
+                executeNextState(UnifiedRestoreState.FINAL);
                 return;
-            } finally {
-                executeNextState(nextState);
             }
         }
 
@@ -7267,6 +7234,13 @@
 
             final UnifiedRestoreState nextState;
             switch (mState) {
+                case INITIAL:
+                    // We've just (manually) restored the PMBA.  It doesn't need the
+                    // additional restore-finished callback so we bypass that and go
+                    // directly to running the queue.
+                    nextState = UnifiedRestoreState.RUNNING_QUEUE;
+                    break;
+
                 case RESTORE_KEYVALUE:
                 case RESTORE_FULL: {
                     // Okay, we've just heard back from the agent that it's done with
@@ -8187,6 +8161,9 @@
                 pkg.packageName = packageName;
 
                 mWakelock.acquire();
+                if (MORE_DEBUG) {
+                    Slog.d(TAG, "Restore at install of " + packageName);
+                }
                 Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
                 msg.obj = new RestoreParams(transport, dirName, null,
                         restoreSet, pkg, token);
@@ -8368,6 +8345,9 @@
                     if (token == mRestoreSets[i].token) {
                         long oldId = Binder.clearCallingIdentity();
                         mWakelock.acquire();
+                        if (MORE_DEBUG) {
+                            Slog.d(TAG, "restoreAll() kicking off");
+                        }
                         Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
                         msg.obj = new RestoreParams(mRestoreTransport, dirName,
                                 observer, token);
@@ -8439,6 +8419,9 @@
                     if (token == mRestoreSets[i].token) {
                         long oldId = Binder.clearCallingIdentity();
                         mWakelock.acquire();
+                        if (MORE_DEBUG) {
+                            Slog.d(TAG, "restoreSome() of " + packages.length + " packages");
+                        }
                         Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
                         msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, token,
                                 packages, packages.length > 1);
@@ -8518,6 +8501,9 @@
             // Ready to go:  enqueue the restore request and claim success
             long oldId = Binder.clearCallingIdentity();
             mWakelock.acquire();
+            if (MORE_DEBUG) {
+                Slog.d(TAG, "restorePackage() : " + packageName);
+            }
             Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
             msg.obj = new RestoreParams(mRestoreTransport, dirName,
                     observer, token, app, 0);
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index f64e97f..fcca788 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -37,7 +37,6 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.EOFException;
-import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -48,9 +47,6 @@
 import java.util.Set;
 
 import java.util.Objects;
-import java.util.Map.Entry;
-
-import libcore.io.IoUtils;
 
 /**
  * We back up the signatures of each package so that during a system restore,
@@ -132,93 +128,6 @@
         mStoredIncrementalVersion = Build.VERSION.INCREMENTAL;
     }
 
-    /**
-     * Reconstitute a PMBA from its on-disk format.  This is used for persistence
-     * of the ancestral dataset's metadata.  See {@link #saveToDisk()} for
-     * details of the file format.
-     */
-    PackageManagerBackupAgent(File cache) throws IOException {
-        FileInputStream fin = new FileInputStream(cache);
-        BufferedInputStream bin = new BufferedInputStream(fin, 32 * 1024);
-        DataInputStream in = new DataInputStream(bin);
-
-        int version = in.readInt();
-        // We can currently only handle the initial version format
-        if (version == ANCESTRAL_RECORD_VERSION) {
-            mStoredSdkVersion = in.readInt();
-            mStoredIncrementalVersion = in.readUTF();
-
-            int nPackages = in.readInt();
-            if (nPackages > 0) {
-                HashMap<String, Metadata> restoredMetadata =
-                        new HashMap<String, Metadata>(nPackages);
-                ArrayList<byte[]> hashes = null;
-                for (int pack = 0; pack < nPackages; pack++) {
-                    final String name = in.readUTF();
-                    final int versionCode = in.readInt();
-                    final int nHashes = in.readInt();
-                    if (nHashes > 0) {
-                        hashes = new ArrayList<byte[]>(nHashes);
-                        for (int i = 0; i < nHashes; i++) {
-                            int len = in.readInt();
-                            byte[] hash = new byte[len];
-                            in.read(hash);
-                            hashes.add(hash);
-                        }
-                    }
-                    restoredMetadata.put(name, new Metadata(versionCode, hashes));
-                }
-                mRestoredSignatures = restoredMetadata;
-            }
-        }
-    }
-
-    public void saveToDisk(File cache) throws IOException {
-        // On disk format is very similar to the key/value format:
-        //
-        // Int: disk format version, currently 1
-        // Int: VERSION.SDK_INT of source device
-        // UTF: VERSION.INCREMENTAL string, for reference
-        //
-        // Int: number of packages represented in this file
-        //
-        // Per package if number > 0:
-        //     UTF: package name
-        //     Int: versionCode of the package
-        //     Int: number of signature hash blocks for this package
-        //     Per signature hash block:
-        //         Int: size of block
-        //         byte[]: block itself if size of block > 0
-        FileOutputStream of = new FileOutputStream(cache);
-        BufferedOutputStream bout = new BufferedOutputStream(of, 32*1024);
-        DataOutputStream out = new DataOutputStream(bout);
-
-        out.writeInt(ANCESTRAL_RECORD_VERSION);
-        out.writeInt(mStoredSdkVersion);
-        out.writeUTF(mStoredIncrementalVersion);
-
-        out.writeInt(mRestoredSignatures.size());
-        if (mRestoredSignatures.size() > 0) {
-            Set<Entry<String, Metadata>> entries = mRestoredSignatures.entrySet();
-            for (Entry<String, Metadata> i : entries) {
-                final Metadata m = i.getValue();
-                final int nHashes = (m.sigHashes != null) ? m.sigHashes.size() : 0;
-                out.writeUTF(i.getKey());
-                out.writeInt(m.versionCode);
-                out.writeInt(nHashes);
-                for (int h = 0; h < nHashes; h++) {
-                    byte[] hash = m.sigHashes.get(h);
-                    out.writeInt(hash.length);
-                    if (hash.length > 0) {
-                        out.write(hash);
-                    }
-                }
-            }
-        }
-        out.flush();
-        IoUtils.closeQuietly(out);
-    }
-
     // We will need to refresh our understanding of what is eligible for
     // backup periodically; this entry point serves that purpose.
     public void evaluateStorablePackages() {
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 579c449..5a510a9 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -371,11 +371,10 @@
 
     @Override
     public void setMode(int code, int uid, String packageName, int mode) {
-        if (Binder.getCallingPid() == Process.myPid()) {
-            return;
+        if (Binder.getCallingPid() != Process.myPid()) {
+            mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+                    Binder.getCallingPid(), Binder.getCallingUid(), null);
         }
-        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
-                Binder.getCallingPid(), Binder.getCallingUid(), null);
         verifyIncomingOp(code);
         ArrayList<Callback> repCbs = null;
         code = AppOpsManager.opToSwitch(code);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9945909..abee0c6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -41,7 +41,6 @@
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 
 import android.app.AlarmManager;
-import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -52,9 +51,7 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -185,8 +182,8 @@
 public class ConnectivityService extends IConnectivityManager.Stub {
     private static final String TAG = "ConnectivityService";
 
-    private static final boolean DBG = true;
-    private static final boolean VDBG = true; // STOPSHIP
+    private static final boolean DBG = false;
+    private static final boolean VDBG = false; // STOPSHIP
 
     // network sampling debugging
     private static final boolean SAMPLE_DBG = false;
@@ -224,10 +221,6 @@
 
     AlarmManager mAlarmManager;
 
-    // used in recursive route setting to add gateways for the host for which
-    // a host route was requested.
-    private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
-
     private Tethering mTethering;
 
     private KeyStore mKeyStore;
@@ -261,11 +254,6 @@
     private CaptivePortalTracker mCaptivePortalTracker;
 
     /**
-     * The link properties that define the current links
-     */
-    private LinkProperties mCurrentLinkProperties[];
-
-    /**
      * A per Net list of the PID's that requested access to the net
      * used both as a refcount and for per-PID DNS selection
      */
@@ -297,15 +285,6 @@
     private static final int ENABLED  = 1;
     private static final int DISABLED = 0;
 
-    private static final boolean ADD = true;
-    private static final boolean REMOVE = false;
-
-    private static final boolean TO_DEFAULT_TABLE = true;
-    private static final boolean TO_SECONDARY_TABLE = false;
-
-    private static final boolean EXEMPT = true;
-    private static final boolean UNEXEMPT = false;
-
     /**
      * used internally as a delayed event to make us switch back to the
      * default network
@@ -450,19 +429,6 @@
 
     private InetAddress mDefaultDns;
 
-    // Lock for protecting access to mAddedRoutes and mExemptAddresses
-    private final Object mRoutesLock = new Object();
-
-    // this collection is used to refcount the added routes - if there are none left
-    // it's time to remove the route from the route table
-    @GuardedBy("mRoutesLock")
-    private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
-
-    // this collection corresponds to the entries of mAddedRoutes that have routing exemptions
-    // used to handle cleanup of exempt rules
-    @GuardedBy("mRoutesLock")
-    private Collection<LinkAddress> mExemptAddresses = new ArrayList<LinkAddress>();
-
     // used in DBG mode to track inet condition reports
     private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
     private ArrayList mInetLog;
@@ -479,8 +445,6 @@
 
     private SettingsObserver mSettingsObserver;
 
-    private AppOpsManager mAppOpsManager;
-
     private UserManager mUserManager;
 
     NetworkConfig[] mNetConfigs;
@@ -514,8 +478,6 @@
     // sequence number of NetworkRequests
     private int mNextNetworkRequestId = 1;
 
-    private static final int UID_UNUSED = -1;
-
     /**
      * Implements support for the legacy "one network per network type" model.
      *
@@ -701,7 +663,6 @@
 
         mNetTrackers = new NetworkStateTracker[
                 ConnectivityManager.MAX_NETWORK_TYPE+1];
-        mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
 
         mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
@@ -884,8 +845,6 @@
         filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
         mContext.registerReceiver(mProvisioningReceiver, filter);
 
-        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
 
@@ -1710,42 +1669,6 @@
     }
 
     /**
-     * Check if the address falls into any of currently running VPN's route's.
-     */
-    private boolean isAddressUnderVpn(InetAddress address) {
-        synchronized (mVpns) {
-            synchronized (mRoutesLock) {
-                int uid = UserHandle.getCallingUserId();
-                Vpn vpn = mVpns.get(uid);
-                if (vpn == null) {
-                    return false;
-                }
-
-                // Check if an exemption exists for this address.
-                for (LinkAddress destination : mExemptAddresses) {
-                    if (!NetworkUtils.addressTypeMatches(address, destination.getAddress())) {
-                        continue;
-                    }
-
-                    int prefix = destination.getPrefixLength();
-                    InetAddress addrMasked = NetworkUtils.getNetworkPart(address, prefix);
-                    InetAddress destMasked = NetworkUtils.getNetworkPart(destination.getAddress(),
-                            prefix);
-
-                    if (addrMasked.equals(destMasked)) {
-                        return false;
-                    }
-                }
-
-                // Finally check if the address is covered by the VPN.
-                return vpn.isAddressCovered(address);
-            }
-        }
-    }
-
-    /**
-     * @deprecated use requestRouteToHostAddress instead
-     *
      * Ensure that a network route exists to deliver traffic to the specified
      * host via the specified network interface.
      * @param networkType the type of the network over which traffic to the
@@ -1754,32 +1677,12 @@
      * desired
      * @return {@code true} on success, {@code false} on failure
      */
-    public boolean requestRouteToHost(int networkType, int hostAddress, String packageName) {
-        InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
-
-        if (inetAddress == null) {
-            return false;
-        }
-
-        return requestRouteToHostAddress(networkType, inetAddress.getAddress(), packageName);
-    }
-
-    /**
-     * Ensure that a network route exists to deliver traffic to the specified
-     * host via the specified network interface.
-     * @param networkType the type of the network over which traffic to the
-     * specified host is to be routed
-     * @param hostAddress the IP address of the host to which the route is
-     * desired
-     * @return {@code true} on success, {@code false} on failure
-     */
-    public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress,
-            String packageName) {
+    public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
         enforceChangePermission();
         if (mProtectedNetworks.contains(networkType)) {
             enforceConnectivityInternalPermission();
         }
-        boolean exempt;
+
         InetAddress addr;
         try {
             addr = InetAddress.getByAddress(hostAddress);
@@ -1787,26 +1690,6 @@
             if (DBG) log("requestRouteToHostAddress got " + e.toString());
             return false;
         }
-        // System apps may request routes bypassing the VPN to keep other networks working.
-        if (Binder.getCallingUid() == Process.SYSTEM_UID) {
-            exempt = true;
-        } else {
-            mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
-            try {
-                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(packageName,
-                        0);
-                exempt = (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-            } catch (NameNotFoundException e) {
-                throw new IllegalArgumentException("Failed to find calling package details", e);
-            }
-        }
-
-        // Non-exempt routeToHost's can only be added if the host is not covered by the VPN.
-        // This can be either because the VPN's routes do not cover the destination or a
-        // system application added an exemption that covers this destination.
-        if (!exempt && isAddressUnderVpn(addr)) {
-            return false;
-        }
 
         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
@@ -1822,13 +1705,13 @@
             }
             return false;
         }
+
         DetailedState netState;
         synchronized (nai) {
             netState = nai.networkInfo.getDetailedState();
         }
 
-        if ((netState != DetailedState.CONNECTED &&
-                netState != DetailedState.CAPTIVE_PORTAL_CHECK)) {
+        if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) {
             if (VDBG) {
                 log("requestRouteToHostAddress on down network "
                         + "(" + networkType + ") - dropped"
@@ -1836,6 +1719,7 @@
             }
             return false;
         }
+
         final int uid = Binder.getCallingUid();
         final long token = Binder.clearCallingIdentity();
         try {
@@ -1845,7 +1729,7 @@
                 lp = nai.linkProperties;
                 netId = nai.network.netId;
             }
-            boolean ok = modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt, netId, uid);
+            boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
             if (DBG) log("requestRouteToHostAddress ok=" + ok);
             return ok;
         } finally {
@@ -1853,17 +1737,7 @@
         }
     }
 
-    private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable,
-            boolean exempt, int netId) {
-        return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt, netId, false, UID_UNUSED);
-    }
-
-    private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, int netId) {
-        return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT, netId, false, UID_UNUSED);
-    }
-
-    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
-            boolean toDefaultTable, boolean exempt, int netId, int uid) {
+    private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) {
         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
         if (bestRoute == null) {
             bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
@@ -1878,125 +1752,14 @@
                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
             }
         }
-        return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt, netId, true, uid);
-    }
-
-    /*
-     * TODO: Clean all this stuff up. Once we have UID-based routing, stuff will break due to
-     *       incorrect tracking of mAddedRoutes, so a cleanup becomes necessary and urgent. But at
-     *       the same time, there'll be no more need to track mAddedRoutes or mExemptAddresses,
-     *       or even have the concept of an exempt address, or do things like "selectBestRoute", or
-     *       determine "default" vs "secondary" table, etc., so the cleanup becomes possible.
-     */
-    private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd,
-            boolean toDefaultTable, boolean exempt, int netId, boolean legacy, int uid) {
-        if ((lp == null) || (r == null)) {
-            if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r);
+        if (VDBG) log("Adding " + bestRoute + " for interface " + bestRoute.getInterface());
+        try {
+            mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
+        } catch (Exception e) {
+            // never crash - catch them all
+            if (DBG) loge("Exception trying to add a route: " + e);
             return false;
         }
-
-        if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
-            loge("Error modifying route - too much recursion");
-            return false;
-        }
-
-        String ifaceName = r.getInterface();
-        if(ifaceName == null) {
-            loge("Error modifying route - no interface name");
-            return false;
-        }
-        if (r.hasGateway()) {
-            RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), r.getGateway());
-            if (bestRoute != null) {
-                if (bestRoute.getGateway().equals(r.getGateway())) {
-                    // if there is no better route, add the implied hostroute for our gateway
-                    bestRoute = RouteInfo.makeHostRoute(r.getGateway(), ifaceName);
-                } else {
-                    // if we will connect to our gateway through another route, add a direct
-                    // route to it's gateway
-                    bestRoute = RouteInfo.makeHostRoute(r.getGateway(),
-                                                        bestRoute.getGateway(),
-                                                        ifaceName);
-                }
-                modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt, netId,
-                        legacy, uid);
-            }
-        }
-        if (doAdd) {
-            if (VDBG) log("Adding " + r + " for interface " + ifaceName);
-            try {
-                if (toDefaultTable) {
-                    synchronized (mRoutesLock) {
-                        // only track default table - only one apps can effect
-                        mAddedRoutes.add(r);
-                        if (legacy) {
-                            mNetd.addLegacyRouteForNetId(netId, r, uid);
-                        } else {
-                            mNetd.addRoute(netId, r);
-                        }
-                        if (exempt) {
-                            LinkAddress dest = r.getDestinationLinkAddress();
-                            if (!mExemptAddresses.contains(dest)) {
-                                mNetd.setHostExemption(dest);
-                                mExemptAddresses.add(dest);
-                            }
-                        }
-                    }
-                } else {
-                    if (legacy) {
-                        mNetd.addLegacyRouteForNetId(netId, r, uid);
-                    } else {
-                        mNetd.addRoute(netId, r);
-                    }
-                }
-            } catch (Exception e) {
-                // never crash - catch them all
-                if (DBG) loge("Exception trying to add a route: " + e);
-                return false;
-            }
-        } else {
-            // if we remove this one and there are no more like it, then refcount==0 and
-            // we can remove it from the table
-            if (toDefaultTable) {
-                synchronized (mRoutesLock) {
-                    mAddedRoutes.remove(r);
-                    if (mAddedRoutes.contains(r) == false) {
-                        if (VDBG) log("Removing " + r + " for interface " + ifaceName);
-                        try {
-                            if (legacy) {
-                                mNetd.removeLegacyRouteForNetId(netId, r, uid);
-                            } else {
-                                mNetd.removeRoute(netId, r);
-                            }
-                            LinkAddress dest = r.getDestinationLinkAddress();
-                            if (mExemptAddresses.contains(dest)) {
-                                mNetd.clearHostExemption(dest);
-                                mExemptAddresses.remove(dest);
-                            }
-                        } catch (Exception e) {
-                            // never crash - catch them all
-                            if (VDBG) loge("Exception trying to remove a route: " + e);
-                            return false;
-                        }
-                    } else {
-                        if (VDBG) log("not removing " + r + " as it's still in use");
-                    }
-                }
-            } else {
-                if (VDBG) log("Removing " + r + " for interface " + ifaceName);
-                try {
-                    if (legacy) {
-                        mNetd.removeLegacyRouteForNetId(netId, r, uid);
-                    } else {
-                        mNetd.removeRoute(netId, r);
-                    }
-                } catch (Exception e) {
-                    // never crash - catch them all
-                    if (VDBG) loge("Exception trying to remove a route: " + e);
-                    return false;
-                }
-            }
-        }
         return true;
     }
 
@@ -2607,6 +2370,7 @@
      *
      * TODO - delete when we're sure all this functionallity is captured.
      */
+    /*
     private void handleConnectivityChange(int netType, LinkProperties curLp, boolean doReset) {
         int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
         boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType);
@@ -2615,10 +2379,8 @@
                     + " resetMask=" + resetMask);
         }
 
-        /*
-         * If a non-default network is enabled, add the host routes that
-         * will allow it's DNS servers to be accessed.
-         */
+        // If a non-default network is enabled, add the host routes that
+        // will allow it's DNS servers to be accessed.
         handleDnsConfigurationChange(netType);
 
         LinkProperties newLp = null;
@@ -2719,7 +2481,7 @@
 
         // TODO: Temporary notifying upstread change to Tethering.
         //       @see bug/4455071
-        /** Notify TetheringService if interface name has been changed. */
+        //  Notify TetheringService if interface name has been changed.
         if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
                              PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) {
             if (isTetheringSupported()) {
@@ -2727,6 +2489,7 @@
             }
         }
     }
+    */
 
     /**
      * Add and remove routes using the old properties (null if not previously connected),
@@ -2736,6 +2499,7 @@
      * host routes should be set to the dns servers
      * returns a boolean indicating the routes changed
      */
+    /*
     private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
             boolean isLinkDefault, boolean exempt, int netId) {
         Collection<RouteInfo> routesToAdd = null;
@@ -2789,6 +2553,7 @@
 
         return routesChanged;
     }
+    */
 
     /**
      * Reads the network specific MTU size from reources.
@@ -3264,10 +3029,12 @@
                         // any activity by applications trying to use this
                         // connection will fail until the provisioning network
                         // is enabled.
+                        /*
                         for (RouteInfo r : lp.getRoutes()) {
                             removeRoute(lp, r, TO_DEFAULT_TABLE,
                                         mNetTrackers[info.getType()].getNetwork().netId);
                         }
+                        */
                     } else if (state == NetworkInfo.State.DISCONNECTED) {
                     } else if (state == NetworkInfo.State.SUSPENDED) {
                     } else if (state == NetworkInfo.State.CONNECTED) {
@@ -3283,8 +3050,10 @@
                     // TODO: Temporary allowing network configuration
                     //       change not resetting sockets.
                     //       @see bug/4455071
+                    /*
                     handleConnectivityChange(info.getType(), mCurrentLinkProperties[info.getType()],
                             false);
+                    */
                     break;
                 }
                 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
@@ -4683,7 +4452,7 @@
 
                             // Make a route to host so we check the specific interface.
                             if (mCs.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_HIPRI,
-                                    hostAddr.getAddress(), null)) {
+                                    hostAddr.getAddress())) {
                                 // Wait a short time to be sure the route is established ??
                                 log("isMobileOk:"
                                         + " wait to establish route to hostAddr=" + hostAddr);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 2434f71..db423b0 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -108,15 +108,6 @@
     private static final String NETD_TAG = "NetdConnector";
     private static final String NETD_SOCKET_NAME = "netd";
 
-    private static final String ADD = "add";
-    private static final String REMOVE = "remove";
-
-    private static final String ALLOW = "allow";
-    private static final String DENY = "deny";
-
-    private static final String DEFAULT = "default";
-    private static final String SECONDARY = "secondary";
-
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
     /**
@@ -126,7 +117,7 @@
     public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
 
     class NetdResponseCode {
-        /* Keep in sync with system/netd/ResponseCode.h */
+        /* Keep in sync with system/netd/server/ResponseCode.h */
         public static final int InterfaceListResult       = 110;
         public static final int TetherInterfaceListResult = 111;
         public static final int TetherDnsFwdTgtListResult = 112;
@@ -946,15 +937,15 @@
 
     @Override
     public void addRoute(int netId, RouteInfo route) {
-        modifyRoute(netId, ADD, route);
+        modifyRoute("add", "" + netId, route);
     }
 
     @Override
     public void removeRoute(int netId, RouteInfo route) {
-        modifyRoute(netId, REMOVE, route);
+        modifyRoute("remove", "" + netId, route);
     }
 
-    private void modifyRoute(int netId, String action, RouteInfo route) {
+    private void modifyRoute(String action, String netId, RouteInfo route) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         final Command cmd = new Command("network", "route", action, netId);
@@ -1175,6 +1166,11 @@
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
+        List<RouteInfo> routes = new ArrayList<RouteInfo>();
+        // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
+        // suitable to use as a route destination.
+        routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
+        addInterfaceToLocalNetwork(iface, routes);
     }
 
     @Override
@@ -1185,6 +1181,7 @@
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
+        removeInterfaceFromLocalNetwork(iface);
     }
 
     @Override
@@ -1748,36 +1745,6 @@
     }
 
     @Override
-    public void setHostExemption(LinkAddress host) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            mConnector.execute("interface", "fwmark", "exempt", "add", host);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
-    public void clearHostExemption(LinkAddress host) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            mConnector.execute("interface", "fwmark", "exempt", "remove", host);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
-    public void flushNetworkDnsCache(int netId) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            mConnector.execute("resolver", "flushnet", netId);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
     public void setFirewallEnabled(boolean enabled) {
         enforceSystemUid();
         try {
@@ -1798,7 +1765,7 @@
     public void setFirewallInterfaceRule(String iface, boolean allow) {
         enforceSystemUid();
         Preconditions.checkState(mFirewallEnabled);
-        final String rule = allow ? ALLOW : DENY;
+        final String rule = allow ? "allow" : "deny";
         try {
             mConnector.execute("firewall", "set_interface_rule", iface, rule);
         } catch (NativeDaemonConnectorException e) {
@@ -1810,7 +1777,7 @@
     public void setFirewallEgressSourceRule(String addr, boolean allow) {
         enforceSystemUid();
         Preconditions.checkState(mFirewallEnabled);
-        final String rule = allow ? ALLOW : DENY;
+        final String rule = allow ? "allow" : "deny";
         try {
             mConnector.execute("firewall", "set_egress_source_rule", addr, rule);
         } catch (NativeDaemonConnectorException e) {
@@ -1822,7 +1789,7 @@
     public void setFirewallEgressDestRule(String addr, int port, boolean allow) {
         enforceSystemUid();
         Preconditions.checkState(mFirewallEnabled);
-        final String rule = allow ? ALLOW : DENY;
+        final String rule = allow ? "allow" : "deny";
         try {
             mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule);
         } catch (NativeDaemonConnectorException e) {
@@ -1834,7 +1801,7 @@
     public void setFirewallUidRule(int uid, boolean allow) {
         enforceSystemUid();
         Preconditions.checkState(mFirewallEnabled);
-        final String rule = allow ? ALLOW : DENY;
+        final String rule = allow ? "allow" : "deny";
         try {
             mConnector.execute("firewall", "set_uid_rule", uid, rule);
         } catch (NativeDaemonConnectorException e) {
@@ -2003,21 +1970,18 @@
 
     @Override
     public void addInterfaceToNetwork(String iface, int netId) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mConnector.execute("network", "addiface", netId, iface);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
+        modifyInterfaceInNetwork("add", "" + netId, iface);
     }
 
     @Override
     public void removeInterfaceFromNetwork(String iface, int netId) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        modifyInterfaceInNetwork("remove", "" + netId, iface);
+    }
 
+    private void modifyInterfaceInNetwork(String action, String netId, String iface) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("network", "removeiface", netId, iface);
+            mConnector.execute("network", "interface", action, netId, iface);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
@@ -2025,18 +1989,9 @@
 
     @Override
     public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
-        modifyLegacyRouteForNetId(netId, routeInfo, uid, ADD);
-    }
-
-    @Override
-    public void removeLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
-        modifyLegacyRouteForNetId(netId, routeInfo, uid, REMOVE);
-    }
-
-    private void modifyLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid, String action) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        final Command cmd = new Command("network", "route", "legacy", uid, action, netId);
+        final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
 
         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
         final LinkAddress la = routeInfo.getDestinationLinkAddress();
@@ -2131,4 +2086,19 @@
         }
     }
 
+    @Override
+    public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
+        modifyInterfaceInNetwork("add", "local", iface);
+
+        for (RouteInfo route : routes) {
+            if (!route.isDefaultRoute()) {
+                modifyRoute("add", "local", route);
+            }
+        }
+    }
+
+    @Override
+    public void removeInterfaceFromLocalNetwork(String iface) {
+        modifyInterfaceInNetwork("remove", "local", iface);
+    }
 }
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index fe97c71..cf7e65c 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -603,7 +603,7 @@
         return mUniqueId;
     }
 
-    /* These should be in sync with system/netd/mDnsResponseCode.h */
+    /* These should be in sync with system/netd/server/ResponseCode.h */
     class NativeResponseCode {
         public static final int SERVICE_DISCOVERY_FAILED    =   602;
         public static final int SERVICE_FOUND               =   603;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 36d67ee..9a86136 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -77,6 +77,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.FgThread;
+
 import com.google.android.collect.Lists;
 import com.google.android.collect.Sets;
 
@@ -109,7 +110,7 @@
 
     private static final int TIMEOUT_DELAY_MS = 1000 * 60;
     private static final String DATABASE_NAME = "accounts.db";
-    private static final int DATABASE_VERSION = 5;
+    private static final int DATABASE_VERSION = 6;
 
     private final Context mContext;
 
@@ -130,6 +131,7 @@
     private static final String ACCOUNTS_TYPE = "type";
     private static final String ACCOUNTS_TYPE_COUNT = "count(type)";
     private static final String ACCOUNTS_PASSWORD = "password";
+    private static final String ACCOUNTS_PREVIOUS_NAME = "previous_name";
 
     private static final String TABLE_AUTHTOKENS = "authtokens";
     private static final String AUTHTOKENS_ID = "_id";
@@ -196,6 +198,20 @@
         /** protected by the {@link #cacheLock} */
         private final HashMap<Account, HashMap<String, String>> authTokenCache =
                 new HashMap<Account, HashMap<String, String>>();
+        /**
+         * protected by the {@link #cacheLock}
+         *
+         * Caches the previous names associated with an account. Previous names
+         * should be cached because we expect that when an Account is renamed,
+         * many clients will receive a LOGIN_ACCOUNTS_CHANGED broadcast and
+         * want to know if the accounts they care about have been renamed.
+         *
+         * The previous names are wrapped in an {@link AtomicReference} so that
+         * we can distinguish between those accounts with no previous names and
+         * those whose previous names haven't been cached (yet).
+         */
+        private final HashMap<Account, AtomicReference<String>> previousNameCache =
+                new HashMap<Account, AtomicReference<String>>();
 
         UserAccounts(Context context, int userId) {
             this.userId = userId;
@@ -517,6 +533,57 @@
     }
 
     @Override
+    public String getPreviousName(Account account) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "getPreviousName: " + account
+                    + ", caller's uid " + Binder.getCallingUid()
+                    + ", pid " + Binder.getCallingPid());
+        }
+        if (account == null) throw new IllegalArgumentException("account is null");
+        UserAccounts accounts = getUserAccountsForCaller();
+        long identityToken = clearCallingIdentity();
+        try {
+            return readPreviousNameInternal(accounts, account);
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
+    private String readPreviousNameInternal(UserAccounts accounts, Account account) {
+        if  (account == null) {
+            return null;
+        }
+        synchronized (accounts.cacheLock) {
+            AtomicReference<String> previousNameRef = accounts.previousNameCache.get(account);
+            if (previousNameRef == null) {
+                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
+                Cursor cursor = db.query(
+                        TABLE_ACCOUNTS,
+                        new String[]{ ACCOUNTS_PREVIOUS_NAME },
+                        ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+                        new String[] { account.name, account.type },
+                        null,
+                        null,
+                        null);
+                try {
+                    if (cursor.moveToNext()) {
+                        String previousName = cursor.getString(0);
+                        previousNameRef = new AtomicReference<String>(previousName);
+                        accounts.previousNameCache.put(account, previousNameRef);
+                        return previousName;
+                    } else {
+                        return null;
+                    }
+                } finally {
+                    cursor.close();
+                }
+            } else {
+                return previousNameRef.get();
+            }
+        }
+    }
+
+    @Override
     public String getUserData(Account account, String key) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "getUserData: " + account
@@ -859,6 +926,119 @@
     }
 
     @Override
+    public void renameAccount(
+            IAccountManagerResponse response, Account accountToRename, String newName) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "renameAccount: " + accountToRename + " -> " + newName
+                + ", caller's uid " + Binder.getCallingUid()
+                + ", pid " + Binder.getCallingPid());
+        }
+        if (accountToRename == null) throw new IllegalArgumentException("account is null");
+        checkAuthenticateAccountsPermission(accountToRename);
+        UserAccounts accounts = getUserAccountsForCaller();
+        long identityToken = clearCallingIdentity();
+        try {
+            Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName);
+            Bundle result = new Bundle();
+            result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name);
+            result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type);
+            try {
+                response.onResult(result);
+            } catch (RemoteException e) {
+                Log.w(TAG, e.getMessage());
+            }
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
+    private Account renameAccountInternal(
+            UserAccounts accounts, Account accountToRename, String newName) {
+        Account resultAccount = null;
+        /*
+         * Cancel existing notifications. Let authenticators
+         * re-post notifications as required. But we don't know if
+         * the authenticators have bound their notifications to
+         * now stale account name data.
+         *
+         * With a rename api, we might not need to do this anymore but it
+         * shouldn't hurt.
+         */
+        cancelNotification(
+                getSigninRequiredNotificationId(accounts, accountToRename),
+                 new UserHandle(accounts.userId));
+        synchronized(accounts.credentialsPermissionNotificationIds) {
+            for (Pair<Pair<Account, String>, Integer> pair:
+                    accounts.credentialsPermissionNotificationIds.keySet()) {
+                if (accountToRename.equals(pair.first.first)) {
+                    int id = accounts.credentialsPermissionNotificationIds.get(pair);
+                    cancelNotification(id, new UserHandle(accounts.userId));
+                }
+            }
+        }
+        synchronized (accounts.cacheLock) {
+            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+            db.beginTransaction();
+            boolean isSuccessful = false;
+            Account renamedAccount = new Account(newName, accountToRename.type);
+            try {
+                final ContentValues values = new ContentValues();
+                values.put(ACCOUNTS_NAME, newName);
+                values.put(ACCOUNTS_PREVIOUS_NAME, accountToRename.name);
+                final long accountId = getAccountIdLocked(db, accountToRename);
+                if (accountId >= 0) {
+                    final String[] argsAccountId = { String.valueOf(accountId) };
+                    db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
+                    db.setTransactionSuccessful();
+                    isSuccessful = true;
+                }
+            } finally {
+                db.endTransaction();
+                if (isSuccessful) {
+                    /*
+                     * Database transaction was successful. Clean up cached
+                     * data associated with the account in the user profile.
+                     */
+                    insertAccountIntoCacheLocked(accounts, renamedAccount);
+                    /*
+                     * Extract the data and token caches before removing the
+                     * old account to preserve the user data associated with
+                     * the account.
+                     */
+                    HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename);
+                    HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename);
+                    removeAccountFromCacheLocked(accounts, accountToRename);
+                    /*
+                     * Update the cached data associated with the renamed
+                     * account.
+                     */
+                    accounts.userDataCache.put(renamedAccount, tmpData);
+                    accounts.authTokenCache.put(renamedAccount, tmpTokens);
+                    accounts.previousNameCache.put(
+                          renamedAccount,
+                          new AtomicReference<String>(accountToRename.name));
+                    resultAccount = renamedAccount;
+
+                    if (accounts.userId == UserHandle.USER_OWNER) {
+                        /*
+                         * Owner's account was renamed, rename the account for
+                         * those users with which the account was shared.
+                         */
+                        List<UserInfo> users = mUserManager.getUsers(true);
+                        for (UserInfo user : users) {
+                            if (!user.isPrimary() && user.isRestricted()) {
+                                renameSharedAccountAsUser(accountToRename, newName, user.id);
+                            }
+                        }
+                    }
+                    sendAccountsChangedBroadcast(accounts.userId);
+                }
+            }
+        }
+        return resultAccount;
+    }
+
+    @Override
     public void removeAccount(IAccountManagerResponse response, Account account) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "removeAccount: " + account
@@ -2061,6 +2241,26 @@
     }
 
     @Override
+    public boolean renameSharedAccountAsUser(Account account, String newName, int userId) {
+        userId = handleIncomingUser(userId);
+        UserAccounts accounts = getUserAccounts(userId);
+        SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+        final ContentValues values = new ContentValues();
+        values.put(ACCOUNTS_NAME, newName);
+        values.put(ACCOUNTS_PREVIOUS_NAME, account.name);
+        int r = db.update(
+                TABLE_SHARED_ACCOUNTS,
+                values,
+                ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+                new String[] { account.name, account.type });
+        if (r > 0) {
+            // Recursively rename the account.
+            renameAccountInternal(accounts, account, newName);
+        }
+        return r > 0;
+    }
+
+    @Override
     public boolean removeSharedAccountAsUser(Account account, int userId) {
         userId = handleIncomingUser(userId);
         UserAccounts accounts = getUserAccounts(userId);
@@ -2557,6 +2757,7 @@
                     + ACCOUNTS_NAME + " TEXT NOT NULL, "
                     + ACCOUNTS_TYPE + " TEXT NOT NULL, "
                     + ACCOUNTS_PASSWORD + " TEXT, "
+                    + ACCOUNTS_PREVIOUS_NAME + " TEXT, "
                     + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
 
             db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " (  "
@@ -2592,6 +2793,10 @@
                     + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
         }
 
+        private void addOldAccountNameColumn(SQLiteDatabase db) {
+            db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN " + ACCOUNTS_PREVIOUS_NAME);
+        }
+
         private void createAccountsDeletionTrigger(SQLiteDatabase db) {
             db.execSQL(""
                     + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
@@ -2642,6 +2847,11 @@
                 oldVersion++;
             }
 
+            if (oldVersion == 5) {
+                addOldAccountNameColumn(db);
+                oldVersion++;
+            }
+
             if (oldVersion != newVersion) {
                 Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
             }
@@ -3050,6 +3260,7 @@
         }
         accounts.userDataCache.remove(account);
         accounts.authTokenCache.remove(account);
+        accounts.previousNameCache.remove(account);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3aaa402..dcb4f18 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -3545,6 +3546,23 @@
         }
     }
 
+    @Override
+    public final int startActivityFromRecents(int taskId, Bundle options) {
+        if (checkCallingPermission(START_TASKS_FROM_RECENTS) != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: startActivityFromRecents called without " +
+                    START_TASKS_FROM_RECENTS;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+        if (task == null) {
+            throw new ActivityNotFoundException("Task " + taskId + " not found.");
+        }
+        return startActivityInPackage(task.mCallingUid, task.mCallingPackage,
+                task.intent, null, null, null, 0, 0, options, task.userId,
+                null);
+    }
+
     final int startActivityInPackage(int uid, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, Bundle options, int userId,
@@ -8042,8 +8060,8 @@
         boolean checkedGrants = false;
         if (checkUser) {
             // Looking for cross-user grants before enforcing the typical cross-users permissions
-            int tmpTargetUserId = unsafeConvertIncomingUser(UserHandle.getUserId(callingUid));
-            if (tmpTargetUserId != userId) {
+            int tmpTargetUserId = unsafeConvertIncomingUser(userId);
+            if (tmpTargetUserId != UserHandle.getUserId(callingUid)) {
                 if (checkAuthorityGrants(callingUid, cpi, tmpTargetUserId, checkUser)) {
                     return null;
                 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 061053a..69949a4 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -68,6 +68,8 @@
     private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
     private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
     private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
+    private static final String ATTR_CALLING_UID = "calling_uid";
+    private static final String ATTR_CALLING_PACKAGE = "calling_package";
     private static final String LAST_ACTIVITY_ICON_SUFFIX = "_last_activity_icon_";
 
     private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
@@ -144,6 +146,10 @@
     TaskRecord mNextAffiliate; // next task in affiliated chain.
     int mNextAffiliateTaskId = -1; // next id for persistence.
 
+    // For relaunching the task from recents as though it was launched by the original launcher.
+    int mCallingUid;
+    String mCallingPackage;
+
     final ActivityManagerService mService;
 
     TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
@@ -167,7 +173,7 @@
             String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
             long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
             ActivityManager.TaskDescription _lastTaskDescription, int taskAffiliation,
-            int prevTaskId, int nextTaskId) {
+            int prevTaskId, int nextTaskId, int callingUid, String callingPackage) {
         mService = service;
         mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
                 TaskPersister.IMAGE_EXTENSION;
@@ -196,17 +202,19 @@
         mAffiliatedTaskId = taskAffiliation;
         mPrevAffiliateTaskId = prevTaskId;
         mNextAffiliateTaskId = nextTaskId;
+        mCallingUid = callingUid;
+        mCallingPackage = callingPackage;
     }
 
     void touchActiveTime() {
-        lastActiveTime = android.os.SystemClock.elapsedRealtime();
+        lastActiveTime = System.currentTimeMillis();
         if (firstActiveTime == 0) {
             firstActiveTime = lastActiveTime;
         }
     }
 
     long getInactiveDuration() {
-        return android.os.SystemClock.elapsedRealtime() - lastActiveTime;
+        return System.currentTimeMillis() - lastActiveTime;
     }
 
     void setIntent(Intent _intent, ActivityInfo info) {
@@ -458,6 +466,8 @@
         if (mActivities.isEmpty()) {
             taskType = r.mActivityType;
             isPersistable = r.isPersistable();
+            mCallingUid = r.launchedFromUid;
+            mCallingPackage = r.launchedFromPackage;
             // Clamp to [1, 100].
             maxRecents = Math.min(Math.max(r.info.maxRecents, 1), 100);
         } else {
@@ -765,6 +775,8 @@
         out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
         out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
         out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
+        out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
+        out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
 
         if (affinityIntent != null) {
             out.startTag(null, TAG_AFFINITYINTENT);
@@ -816,6 +828,8 @@
         int taskAffiliation = -1;
         int prevTaskId = -1;
         int nextTaskId = -1;
+        int callingUid = -1;
+        String callingPackage = "";
 
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
@@ -858,6 +872,10 @@
                 prevTaskId = Integer.valueOf(attrValue);
             } else if (ATTR_NEXT_AFFILIATION.equals(attrName)) {
                 nextTaskId = Integer.valueOf(attrValue);
+            } else if (ATTR_CALLING_UID.equals(attrName)) {
+                callingUid = Integer.valueOf(attrValue);
+            } else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
+                callingPackage = attrValue;
             } else {
                 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
             }
@@ -898,7 +916,8 @@
                 affinityIntent, affinity, realActivity, origActivity, rootHasReset,
                 autoRemoveRecents, askedCompatMode, taskType, userId, lastDescription, activities,
                 firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
-                taskDescription, taskAffiliation, prevTaskId, nextTaskId);
+                taskDescription, taskAffiliation, prevTaskId, nextTaskId, callingUid,
+                callingPackage);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
             activities.get(activityNdx).task = task;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 01a2fc2..d948942 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -724,14 +724,6 @@
         return retVal;
     }
 
-    //TODO: Temporary handling upstream change triggered without
-    //      CONNECTIVITY_ACTION. Only to accomodate interface
-    //      switch during HO.
-    //      @see bug/4455071
-    public void handleTetherIfaceChange() {
-        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
-    }
-
     class TetherInterfaceSM extends StateMachine {
         // notification from the master SM that it's not in tether mode
         static final int CMD_TETHER_MODE_DEAD            =  1;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index d15254b..7b68d55 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -488,18 +488,6 @@
         return tun;
     }
 
-    /**
-     * Check if a given address is covered by the VPN's routing rules.
-     */
-    public boolean isAddressCovered(InetAddress address) {
-        synchronized (Vpn.this) {
-            if (!isRunningLocked()) {
-                return false;
-            }
-            return RouteInfo.selectBestRoute(mConfig.routes, address) != null;
-        }
-    }
-
     private boolean isRunningLocked() {
         return mVpnUsers != null;
     }
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 1279c6e..64d3dc5 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -719,10 +719,16 @@
 
     @Override
     public void setMasterSyncAutomatically(boolean flag) {
+        setMasterSyncAutomaticallyAsUser(flag, UserHandle.getCallingUserId());
+    }
+
+    @Override
+    public void setMasterSyncAutomaticallyAsUser(boolean flag, int userId) {
+        enforceCrossUserPermission(userId,
+                "no permission to set the sync status for user " + userId);
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
 
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 85c7747..946d4ce 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+
 /**
  * Defines constants related to HDMI-CEC protocol internal implementation.
  * If a constant will be used in the public api, it should be located in
@@ -78,7 +80,7 @@
     public static final int ADDR_INVALID = -1;
 
     /** Logical address used to indicate the source comes from internal device. */
-    public static final int ADDR_INTERNAL = 0xFFFF;
+    public static final int ADDR_INTERNAL = HdmiCecDeviceInfo.ADDR_INTERNAL;
 
     static final int MESSAGE_FEATURE_ABORT = 0x00;
     static final int MESSAGE_IMAGE_VIEW_ON = 0x04;
@@ -179,10 +181,11 @@
     static final int INVALID_PORT_ID = -1;
     static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
 
-    // Send result codes.
+    // Send result codes. It should be consistent with hdmi_cec.h's send_message error code.
     static final int SEND_RESULT_SUCCESS = 0;
-    static final int SEND_RESULT_NAK = -1;
-    static final int SEND_RESULT_FAILURE = -2;
+    static final int SEND_RESULT_NAK = 1;
+    static final int SEND_RESULT_BUSY = 2;
+    static final int SEND_RESULT_FAILURE = 3;
 
     // Strategy for device polling.
     // Should use "OR(|) operation of POLL_STRATEGY_XXX and POLL_ITERATION_XXX.
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index a66f473..e985e35 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -556,6 +556,9 @@
     @ServiceThreadOnly
     private void clearDeviceInfoList() {
         assertRunOnServiceThread();
+        for (HdmiCecDeviceInfo info : mSafeExternalInputs) {
+            mService.invokeDeviceEventListeners(info, false);
+        }
         mDeviceInfos.clear();
         updateSafeDeviceInfoList();
     }
@@ -1129,6 +1132,7 @@
 
         disableSystemAudioIfExist();
         disableArcIfExist();
+        clearDeviceInfoList();
         checkIfPendingActionsCleared();
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 560ee84..95cd7ef 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1013,12 +1013,17 @@
          }
 
         @Override
-        public void setRecordRequestListener(IHdmiRecordRequestListener listener) {
+        public void setOneTouchRecordRequestListener(IHdmiRecordRequestListener listener) {
             // TODO: implement this.
         }
 
         @Override
-        public void startRecord(int recorderAddress, byte[] recordSource) {
+        public void startOneTouchRecord(int recorderAddress, byte[] recordSource) {
+            // TODO: implement this.
+        }
+
+        @Override
+        public void startTimerRecording(int recorderAddress, byte[] recordSource) {
             // TODO: implement this.
         }
     }
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a2dd15e..b0ccd62 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -776,8 +776,8 @@
                 if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0) {
                     if (DEBUG) {
                         Log.d(TAG, "No active session to adjust, skipping media only volume event");
-                        return;
                     }
+                    return;
                 }
                 try {
                     mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, flags,
diff --git a/services/core/java/com/android/server/notification/GroupedNotificationComparator.java b/services/core/java/com/android/server/notification/GroupedNotificationComparator.java
new file mode 100644
index 0000000..608d55c
--- /dev/null
+++ b/services/core/java/com/android/server/notification/GroupedNotificationComparator.java
@@ -0,0 +1,57 @@
+/*
+ * 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.server.notification;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * Sorts notifications, accounting for groups and sort keys.
+ */
+public class GroupedNotificationComparator extends NotificationComparator {
+    private static final String TAG = "GroupedNotificationComparator";
+
+    @Override
+    public int compare(NotificationRecord left, NotificationRecord right) {
+        // "recently intrusive" is an ad hoc group that temporarily claims noisy notifications
+        if (left.isRecentlyIntrusive() != right.isRecentlyIntrusive()) {
+            return left.isRecentlyIntrusive() ? -1 : 1;
+        }
+
+        final NotificationRecord leftProxy = left.getRankingProxy();
+        if (leftProxy == null) {
+            throw new RuntimeException("left proxy cannot be null: " + left.getKey());
+        }
+        final NotificationRecord rightProxy = right.getRankingProxy();
+        if (rightProxy == null) {
+            throw new RuntimeException("right proxy cannot be null: " + right.getKey());
+        }
+        final String leftSortKey = left.getNotification().getSortKey();
+        final String rightSortKey = right.getNotification().getSortKey();
+        if (leftProxy != rightProxy) {
+            // between groups, compare proxies
+            return Integer.compare(leftProxy.getAuthoritativeRank(),
+                    rightProxy.getAuthoritativeRank());
+        } else if (TextUtils.isEmpty(leftSortKey) || TextUtils.isEmpty(rightSortKey)) {
+            // missing sort keys, use prior rank
+            return Integer.compare(left.getAuthoritativeRank(),
+                    right.getAuthoritativeRank());
+        } else {
+            // use sort keys within group
+            return leftSortKey.compareTo(rightSortKey);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 0546a55..ec81fd2 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -18,35 +18,35 @@
 import java.util.Comparator;
 
 /**
- * Sorts notificaitons into attention-relelvant order.
+ * Sorts notifications individually into attention-relelvant order.
  */
 public class NotificationComparator
         implements Comparator<NotificationRecord> {
 
     @Override
-    public int compare(NotificationRecord lhs, NotificationRecord rhs) {
-        if (lhs.isRecentlyIntrusive() != rhs.isRecentlyIntrusive()) {
-            return lhs.isRecentlyIntrusive() ? -1 : 1;
-        }
-        final int leftPackagePriority = lhs.getPackagePriority();
-        final int rightPackagePriority = rhs.getPackagePriority();
+    public int compare(NotificationRecord left, NotificationRecord right) {
+        final int leftPackagePriority = left.getPackagePriority();
+        final int rightPackagePriority = right.getPackagePriority();
         if (leftPackagePriority != rightPackagePriority) {
             // by priority, high to low
             return -1 * Integer.compare(leftPackagePriority, rightPackagePriority);
         }
-        final int leftScore = lhs.sbn.getScore();
-        final int rightScore = rhs.sbn.getScore();
+
+        final int leftScore = left.sbn.getScore();
+        final int rightScore = right.sbn.getScore();
         if (leftScore != rightScore) {
             // by priority, high to low
             return -1 * Integer.compare(leftScore, rightScore);
         }
-        final float leftPeple = lhs.getContactAffinity();
-        final float rightPeople = rhs.getContactAffinity();
-        if (leftPeple != rightPeople) {
+
+        final float leftPeople = left.getContactAffinity();
+        final float rightPeople = right.getContactAffinity();
+        if (leftPeople != rightPeople) {
             // by contact proximity, close to far
-            return -1 * Float.compare(leftPeple, rightPeople);
+            return -1 * Float.compare(leftPeople, rightPeople);
         }
+
         // then break ties by time, most recent first
-        return -1 * Long.compare(lhs.getRankingTimeMs(), rhs.getRankingTimeMs());
+        return -1 * Long.compare(left.getRankingTimeMs(), right.getRankingTimeMs());
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f69c066..a6711c3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.notification;
 
+import static android.service.notification.NotificationListenerService.FLAG_DISABLE_HOST_ALERTS;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -71,6 +72,7 @@
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
@@ -121,6 +123,7 @@
     static final int MESSAGE_RECONSIDER_RANKING = 4;
     static final int MESSAGE_RANKING_CONFIG_CHANGE = 5;
     static final int MESSAGE_SEND_RANKING_UPDATE = 6;
+    static final int MESSAGE_LISTENER_FLAGS_CHANGED = 7;
 
     static final int LONG_DELAY = 3500; // 3.5 seconds
     static final int SHORT_DELAY = 2000; // 2 seconds
@@ -169,6 +172,9 @@
     NotificationRecord mSoundNotification;
     NotificationRecord mVibrateNotification;
 
+    private final ArraySet<ManagedServiceInfo> mListenersDisablingAlerts = new ArraySet<>();
+    private int mListenerFlags;  // right now, all flags are global
+
     // for enabling and disabling notification pulse behavior
     private boolean mScreenOn = true;
     private boolean mInCall = false;
@@ -463,7 +469,7 @@
         public void onSetDisabled(int status) {
             synchronized (mNotificationList) {
                 mDisableNotificationAlerts = (status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
-                if (mDisableNotificationAlerts) {
+                if (disableNotificationAlerts()) {
                     // cancel whatever's going on
                     long identity = Binder.clearCallingIdentity();
                     try {
@@ -904,6 +910,13 @@
         }
     }
 
+    private void updateListenerFlagsLocked() {
+        final int flags = mListenersDisablingAlerts.isEmpty() ? 0 : FLAG_DISABLE_HOST_ALERTS;
+        if (flags == mListenerFlags) return;
+        mListenerFlags = flags;
+        scheduleListenerFlagsChanged(flags);
+    }
+
     private final IBinder mService = new INotificationManager.Stub() {
         // Toasts
         // ============================================================================
@@ -1249,6 +1262,27 @@
         }
 
         @Override
+        public void requestFlagsFromListener(INotificationListener token, int flags) {
+            synchronized (mNotificationList) {
+                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                final boolean disableAlerts = (flags & FLAG_DISABLE_HOST_ALERTS) != 0;
+                if (disableAlerts) {
+                    mListenersDisablingAlerts.add(info);
+                } else {
+                    mListenersDisablingAlerts.remove(info);
+                }
+                updateListenerFlagsLocked();
+            }
+        }
+
+        @Override
+        public int getFlagsFromListener(INotificationListener token) {
+            synchronized (mNotificationList) {
+                return mListenerFlags;
+            }
+        }
+
+        @Override
         public ZenModeConfig getZenModeConfig() {
             enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
             return mZenModeHelper.getConfig();
@@ -1339,6 +1373,10 @@
         return keys.toArray(new String[keys.size()]);
     }
 
+    private boolean disableNotificationAlerts() {
+        return mDisableNotificationAlerts || (mListenerFlags & FLAG_DISABLE_HOST_ALERTS) != 0;
+    }
+
     void dumpImpl(PrintWriter pw, DumpFilter filter) {
         pw.print("Current Notification Manager state");
         if (filter != null) {
@@ -1422,6 +1460,15 @@
 
                 pw.println("\n  Notification listeners:");
                 mListeners.dump(pw, filter);
+                pw.print("    mListenerFlags: "); pw.println(mListenerFlags);
+                pw.print("    mListenersDisablingAlerts: (");
+                N = mListenersDisablingAlerts.size();
+                for (int i = 0; i < N; i++) {
+                    final ManagedServiceInfo listener = mListenersDisablingAlerts.valueAt(i);
+                    if (i > 0) pw.print(',');
+                    pw.print(listener.component);
+                }
+                pw.println(')');
             }
 
             pw.println("\n  Condition providers:");
@@ -1618,7 +1665,7 @@
         }
 
         // If we're not supposed to beep, vibrate, etc. then don't.
-        if (!mDisableNotificationAlerts
+        if (!disableNotificationAlerts()
                 && (!(record.isUpdate
                     && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                 && (record.getUserId() == UserHandle.USER_ALL ||
@@ -1920,6 +1967,17 @@
         }
     }
 
+    private void scheduleListenerFlagsChanged(int state) {
+        mHandler.removeMessages(MESSAGE_LISTENER_FLAGS_CHANGED);
+        mHandler.obtainMessage(MESSAGE_LISTENER_FLAGS_CHANGED, state, 0).sendToTarget();
+    }
+
+    private void handleListenerFlagsChanged(int state) {
+        synchronized (mNotificationList) {
+            mListeners.notifyListenerFlagsChangedLocked(state);
+        }
+    }
+
     private final class WorkerHandler extends Handler
     {
         @Override
@@ -1936,6 +1994,9 @@
                 case MESSAGE_SEND_RANKING_UPDATE:
                     handleSendRankingUpdate();
                     break;
+                case MESSAGE_LISTENER_FLAGS_CHANGED:
+                    handleListenerFlagsChanged(msg.arg1);
+                    break;
             }
         }
 
@@ -2445,6 +2506,13 @@
             }
         }
 
+        @Override
+        protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
+            if (mListenersDisablingAlerts.remove(removed)) {
+                updateListenerFlagsLocked();
+            }
+        }
+
         /**
          * asynchronously notify all listeners about a new notification
          */
@@ -2509,6 +2577,20 @@
             }
         }
 
+        public void notifyListenerFlagsChangedLocked(final int flags) {
+            for (final ManagedServiceInfo serviceInfo : mServices) {
+                if (!serviceInfo.isEnabledForCurrentProfiles()) {
+                    continue;
+                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        notifyListenerFlagsChanged(serviceInfo, flags);
+                    }
+                });
+            }
+        }
+
         private void notifyPostedIfUserMatch(final ManagedServiceInfo info,
                 final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
             if (!info.enabledAndUserMatches(sbn.getUserId())) {
@@ -2544,6 +2626,15 @@
                 Log.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
             }
         }
+
+        private void notifyListenerFlagsChanged(ManagedServiceInfo info, int state) {
+            final INotificationListener listener = (INotificationListener) info.service;
+            try {
+                listener.onListenerFlagsChanged(state);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "unable to notify listener (listener flags): " + listener, ex);
+            }
+        }
     }
 
     public static final class DumpFilter {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 088b813..57f3e2d 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.service.notification.StatusBarNotification;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
 import java.lang.reflect.Array;
@@ -60,7 +61,12 @@
     public boolean isUpdate;
     private int mPackagePriority;
 
-    NotificationRecord(StatusBarNotification sbn, int score)
+    // The record that ranking should use for comparisons outside the group.
+    private NotificationRecord mRankingProxy;
+    private int mAuthoritativeRank;
+
+    @VisibleForTesting
+    public NotificationRecord(StatusBarNotification sbn, int score)
     {
         this.sbn = sbn;
         this.score = score;
@@ -73,7 +79,9 @@
         mRecentlyIntrusive = previous.mRecentlyIntrusive;
         mPackagePriority = previous.mPackagePriority;
         mIntercept = previous.mIntercept;
+        mRankingProxy = previous.mRankingProxy;
         mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
+        // Don't copy mGroupKey, recompute it, in case it has changed
     }
 
     public Notification getNotification() { return sbn.getNotification(); }
@@ -89,6 +97,7 @@
                 + " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon));
         pw.println(prefix + "  pri=" + notification.priority + " score=" + sbn.getScore());
         pw.println(prefix + "  key=" + sbn.getKey());
+        pw.println(prefix + "  groupKey=" + getGroupKey());
         pw.println(prefix + "  contentIntent=" + notification.contentIntent);
         pw.println(prefix + "  deleteIntent=" + notification.deleteIntent);
         pw.println(prefix + "  tickerText=" + notification.tickerText);
@@ -145,6 +154,7 @@
         pw.println(prefix + "  mRecentlyIntrusive=" + mRecentlyIntrusive);
         pw.println(prefix + "  mPackagePriority=" + mPackagePriority);
         pw.println(prefix + "  mIntercept=" + mIntercept);
+        pw.println(prefix + "  mRankingProxy=" + getRankingProxy().getKey());
         pw.println(prefix + "  mRankingTimeMs=" + mRankingTimeMs);
     }
 
@@ -241,4 +251,24 @@
         }
         return sbn.getPostTime();
     }
+
+    public NotificationRecord getRankingProxy() {
+        return mRankingProxy;
+    }
+
+    public void setRankingProxy(NotificationRecord proxy) {
+        mRankingProxy = proxy;
+    }
+
+    public void setAuthoritativeRank(int authoritativeRank) {
+        mAuthoritativeRank = authoritativeRank;
+    }
+
+    public int getAuthoritativeRank() {
+        return mAuthoritativeRank;
+    }
+
+    public String getGroupKey() {
+        return sbn.getGroupKey();
+    }
 }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index fc03c17..d59e17b 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -17,12 +17,12 @@
 
 import android.app.Notification;
 import android.content.Context;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Slog;
 import android.util.SparseIntArray;
 import org.xmlpull.v1.XmlPullParser;
@@ -49,13 +49,13 @@
     private static final String ATT_UID = "uid";
     private static final String ATT_PRIORITY = "priority";
 
-    private static final String VALUE_HIGH = "high";
-
     private final NotificationSignalExtractor[] mSignalExtractors;
-    private final NotificationComparator mRankingComparator = new NotificationComparator();
+    private final NotificationComparator mPreliminaryComparator = new NotificationComparator();
+    private final NotificationComparator mFinalComparator = new GroupedNotificationComparator();
 
     // Package name to uid, to priority. Would be better as Table<String, Int, Int>
     private final ArrayMap<String, SparseIntArray> mPackagePriorities;
+    private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp;
 
     private final Context mContext;
     private final Handler mRankingHandler;
@@ -83,6 +83,7 @@
                 Slog.w(TAG, "Problem accessing extractor " + extractorNames[i] + ".", e);
             }
         }
+        mProxyByGroupTmp = new ArrayMap<String, NotificationRecord>();
     }
 
     public void extractSignals(NotificationRecord r) {
@@ -166,11 +167,39 @@
     }
 
     public void sort(ArrayList<NotificationRecord> notificationList) {
-        Collections.sort(notificationList, mRankingComparator);
+        final int N = notificationList.size();
+        // clear group proxies
+        for (int i = N - 1; i >= 0; i--) {
+            notificationList.get(i).setRankingProxy(null);
+        }
+
+        // rank each record individually
+        Collections.sort(notificationList, mPreliminaryComparator);
+
+        // record inidivdual ranking result and nominate proxies for each group
+        for (int i = N - 1; i >= 0; i--) {
+            final NotificationRecord record = notificationList.get(i);
+            record.setAuthoritativeRank(i);
+            final String groupKey = record.getGroupKey();
+            boolean isGroupSummary = record.getNotification().getGroup() != null
+                    && (record.getNotification().flags & Notification.FLAG_GROUP_SUMMARY) != 0;
+            if (isGroupSummary || mProxyByGroupTmp.get(groupKey) == null) {
+                mProxyByGroupTmp.put(groupKey, record);
+            }
+        }
+        // assign nominated proxies to each notification
+        for (int i = 0; i < N; i++) {
+            final NotificationRecord record = notificationList.get(i);
+            record.setRankingProxy(mProxyByGroupTmp.get(record.getGroupKey()));
+        }
+        // Do a second ranking pass, using group proxies
+        Collections.sort(notificationList, mFinalComparator);
+
+        mProxyByGroupTmp.clear();
     }
 
     public int indexOf(ArrayList<NotificationRecord> notificationList, NotificationRecord target) {
-        return Collections.binarySearch(notificationList, target, mRankingComparator);
+        return Collections.binarySearch(notificationList, target, mFinalComparator);
     }
 
     private static int safeInt(XmlPullParser parser, String att, int defValue) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 8e625c5..a896550 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -90,9 +90,6 @@
             "com.android.mms",
             "com.android.example.notificationshowcase"
             ));
-    private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList(
-            "com.google.android.deskclock"
-            ));
     private static final Set<String> SYSTEM_PACKAGES = new HashSet<String>(Arrays.asList(
             "android",
             "com.android.systemui"
@@ -313,7 +310,8 @@
     }
 
     private boolean isAlarm(NotificationRecord record) {
-        return ALARM_PACKAGES.contains(record.sbn.getPackageName());
+        return record.isCategory(Notification.CATEGORY_ALARM)
+                || record.isCategory(Notification.CATEGORY_EVENT);
     }
 
     private boolean isCall(NotificationRecord record) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6de8a8b..69f2f32 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -474,6 +474,9 @@
     final SparseArray<PackageVerificationState> mPendingVerification
             = new SparseArray<PackageVerificationState>();
 
+    /** Set of packages associated with each app op permission. */
+    final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
+
     final PackageInstallerService mInstallerService;
 
     HashSet<PackageParser.Package> mDeferredDexOpt = null;
@@ -2917,6 +2920,17 @@
     }
 
     @Override
+    public String[] getAppOpPermissionPackages(String permissionName) {
+        synchronized (mPackages) {
+            ArraySet<String> pkgs = mAppOpPermissionPackages.get(permissionName);
+            if (pkgs == null) {
+                return null;
+            }
+            return pkgs.toArray(new String[pkgs.size()]);
+        }
+    }
+
+    @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
@@ -6591,6 +6605,31 @@
                     r.append(p.info.name);
                 }
             }
+            if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
+                ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(p.info.name);
+                if (appOpPerms != null) {
+                    appOpPerms.remove(pkg.packageName);
+                }
+            }
+        }
+        if (r != null) {
+            if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
+        }
+
+        N = pkg.requestedPermissions.size();
+        r = null;
+        for (i=0; i<N; i++) {
+            String perm = pkg.requestedPermissions.get(i);
+            BasePermission bp = mSettings.mPermissions.get(perm);
+            if (bp != null && (bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
+                ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(perm);
+                if (appOpPerms != null) {
+                    appOpPerms.remove(pkg.packageName);
+                    if (appOpPerms.isEmpty()) {
+                        mAppOpPermissionPackages.remove(perm);
+                    }
+                }
+            }
         }
         if (r != null) {
             if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
@@ -6775,6 +6814,15 @@
             final String perm = bp.name;
             boolean allowed;
             boolean allowedSig = false;
+            if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
+                // Keep track of app op permissions.
+                ArraySet<String> pkgs = mAppOpPermissionPackages.get(bp.name);
+                if (pkgs == null) {
+                    pkgs = new ArraySet<>();
+                    mAppOpPermissionPackages.put(bp.name, pkgs);
+                }
+                pkgs.add(pkg.packageName);
+            }
             final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
             if (level == PermissionInfo.PROTECTION_NORMAL
                     || level == PermissionInfo.PROTECTION_DANGEROUS) {
@@ -6837,7 +6885,9 @@
                             + " (protectionLevel=" + bp.protectionLevel
                             + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
                             + ")");
-                } else {
+                } else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
+                    // Don't print warning for app op permissions, since it is fine for them
+                    // not to be granted, there is a UI for the user to decide.
                     Slog.w(TAG, "Not granting permission " + perm
                             + " to package " + pkg.packageName
                             + " (protectionLevel=" + bp.protectionLevel
@@ -12426,6 +12476,22 @@
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
                 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
+                if (packageName == null) {
+                    for (int iperm=0; iperm<mAppOpPermissionPackages.size(); iperm++) {
+                        if (iperm == 0) {
+                            if (dumpState.onTitlePrinted())
+                                pw.println();
+                            pw.println("AppOp Permissions:");
+                        }
+                        pw.print("  AppOp Permission ");
+                        pw.print(mAppOpPermissionPackages.keyAt(iperm));
+                        pw.println(":");
+                        ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
+                        for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
+                            pw.print("    "); pw.println(pkgs.valueAt(ipkg));
+                        }
+                    }
+                }
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 8854869..ea19012 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -211,9 +211,6 @@
     }
 
     public void addHardwareTvInput(int deviceId, TvInputInfo info) {
-        if (info.getType() == TvInputInfo.TYPE_VIRTUAL) {
-            throw new IllegalArgumentException("info (" + info + ") has virtual type.");
-        }
         synchronized (mLock) {
             String oldInputId = mHardwareInputIdMap.get(deviceId);
             if (oldInputId != null) {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 01aaca0..d7ecd7a 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -993,7 +993,10 @@
                 synchronized (mLock) {
                     try {
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri);
-
+                        if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) {
+                            // Do not log the watch history for passthrough inputs.
+                            return;
+                        }
                         long currentTime = System.currentTimeMillis();
                         long channelId = ContentUris.parseId(channelUri);
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fa22ded..aae2bb8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -803,14 +803,14 @@
         mActivityManager = ActivityManagerNative.getDefault();
         mBatteryStats = BatteryStatsService.getService();
         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
-        mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
+        AppOpsManager.OnOpChangedInternalListener opListener =
                 new AppOpsManager.OnOpChangedInternalListener() {
-                    @Override
-                    public void onOpChanged(int op, String packageName) {
+                    @Override public void onOpChanged(int op, String packageName) {
                         updateAppOpsState();
                     }
-                }
-        );
+                };
+        mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener);
+        mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
 
         // Get persisted window scale setting
         mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
@@ -4852,8 +4852,11 @@
         // Where to start adding?
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
             final int numTokens = tokens.size();
+            if (numTokens == 0) {
+                continue;
+            }
+            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
             for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
                 final AppWindowToken wtoken = tokens.get(tokenNdx);
                 if (wtoken != null) {
@@ -5672,13 +5675,28 @@
             throw new SecurityException("Requires READ_FRAME_BUFFER permission");
         }
 
+        final DisplayContent displayContent = getDisplayContentLocked(displayId);
+        if (displayContent == null) {
+            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
+                    + ": returning null. No Display for displayId=" + displayId);
+            return null;
+        }
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        int dw = displayInfo.logicalWidth;
+        int dh = displayInfo.logicalHeight;
+        if (dw == 0 || dh == 0) {
+            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
+                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
+            return null;
+        }
+
         Bitmap rawss = null;
 
         int maxLayer = 0;
         final Rect frame = new Rect();
+        final Rect stackBounds = new Rect();
 
         float scale = 0;
-        int dw, dh;
         int rot = Surface.ROTATION_0;
 
         boolean screenshotReady;
@@ -5694,7 +5712,15 @@
         int retryCount = 0;
         WindowState appWin = null;
 
-        do {
+        final boolean appIsImTarget = mInputMethodTarget != null
+                && mInputMethodTarget.mAppToken != null
+                && mInputMethodTarget.mAppToken.appToken != null
+                && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
+
+        final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
+                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
+
+        while (true) {
             if (retryCount++ > 0) {
                 try {
                     Thread.sleep(100);
@@ -5702,28 +5728,9 @@
                 }
             }
             synchronized(mWindowMap) {
-                final DisplayContent displayContent = getDisplayContentLocked(displayId);
-                if (displayContent == null) {
-                    return null;
-                }
-                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-                dw = displayInfo.logicalWidth;
-                dh = displayInfo.logicalHeight;
-
-                int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
-                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
-                aboveAppLayer += TYPE_LAYER_MULTIPLIER;
-
-                boolean isImeTarget = mInputMethodTarget != null
-                        && mInputMethodTarget.mAppToken != null
-                        && mInputMethodTarget.mAppToken.appToken != null
-                        && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
-
                 // Figure out the part of the screen that is actually the app.
-                boolean including = false;
                 appWin = null;
                 final WindowList windows = displayContent.getWindowList();
-                final Rect stackBounds = new Rect();
                 for (int i = windows.size() - 1; i >= 0; i--) {
                     WindowState ws = windows.get(i);
                     if (!ws.mHasSurface) {
@@ -5732,27 +5739,22 @@
                     if (ws.mLayer >= aboveAppLayer) {
                         continue;
                     }
-                    // When we will skip windows: when we are not including
-                    // ones behind a window we didn't skip, and we are actually
-                    // taking a screenshot of a specific app.
-                    if (!including && appToken != null) {
-                        // Also, we can possibly skip this window if it is not
-                        // an IME target or the application for the screenshot
-                        // is not the current IME target.
-                        if (!ws.mIsImWindow || !isImeTarget) {
-                            // And finally, this window is of no interest if it
-                            // is not associated with the screenshot app.
-                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
-                                continue;
-                            }
-                            appWin = ws;
-                            ws.getStackBounds(stackBounds);
+                    if (ws.mIsImWindow) {
+                        if (!appIsImTarget) {
+                            continue;
                         }
+                    } else if (ws.mIsWallpaper) {
+                        // Fall through.
+                    } else if (appToken != null) {
+                        if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
+                            // This app window is of no interest if it is not associated with the
+                            // screenshot app.
+                            continue;
+                        }
+                        appWin = ws;
                     }
 
-                    // We keep on including windows until we go past a full-screen
-                    // window.
-                    including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
+                    // Include this window.
 
                     final WindowStateAnimator winAnim = ws.mWinAnimator;
                     if (maxLayer < winAnim.mSurfaceLayer) {
@@ -5771,6 +5773,7 @@
                         int right = wf.right - cr.right;
                         int bottom = wf.bottom - cr.bottom;
                         frame.union(left, top, right, bottom);
+                        ws.getStackBounds(stackBounds);
                         frame.intersect(stackBounds);
                     }
 
@@ -5786,60 +5789,49 @@
                             "Screenshot: Couldn't find a surface matching " + appToken);
                     return null;
                 }
+
                 if (!screenshotReady) {
+                    if (retryCount > MAX_SCREENSHOT_RETRIES) {
+                        Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken +
+                                " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
+                                appWin.mWinAnimator.mDrawState)));
+                        return null;
+                    }
+
                     // Delay and hope that window gets drawn.
                     if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
                             + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
                     continue;
                 }
 
-                // Constrain frame to the screen size.
-                frame.intersect(0, 0, dw, dh);
+                // Screenshot is ready to be taken. Everything from here below will continue
+                // through the bottom of the loop and return a value. We only stay in the loop
+                // because we don't want to release the mWindowMap lock until the screenshot is
+                // taken.
 
-                if (frame.isEmpty() || maxLayer == 0) {
+                if (maxLayer == 0) {
                     if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
-                            + ": returning null frame=" + frame.toShortString() + " maxLayer="
-                            + maxLayer);
+                            + ": returning null maxLayer=" + maxLayer);
                     return null;
                 }
 
-                // The screenshot API does not apply the current screen rotation.
-                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
-                int fw = frame.width();
-                int fh = frame.height();
-
+                // Constrain frame to the screen size.
+                frame.intersect(0, 0, dw, dh);
                 // Constrain thumbnail to smaller of screen width or height. Assumes aspect
                 // of thumbnail is the same as the screen (in landscape) or square.
-                scale = Math.max(width / (float) fw, height / (float) fh);
-                /*
-                float targetWidthScale = width / (float) fw;
-                float targetHeightScale = height / (float) fh;
-                if (fw <= fh) {
-                    scale = targetWidthScale;
-                    // If aspect of thumbnail is the same as the screen (in landscape),
-                    // select the slightly larger value so we fill the entire bitmap
-                    if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
-                        scale = targetHeightScale;
-                    }
-                } else {
-                    scale = targetHeightScale;
-                    // If aspect of thumbnail is the same as the screen (in landscape),
-                    // select the slightly larger value so we fill the entire bitmap
-                    if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
-                        scale = targetWidthScale;
-                    }
-                }
-                */
+                scale = Math.max(width / (float) frame.width(), height / (float) frame.height());
+                dw = (int)(dw * scale);
+                dh = (int)(dh * scale);
 
-                // The screen shot will contain the entire screen.
-                dw = (int)(dw*scale);
-                dh = (int)(dh*scale);
+                // The screenshot API does not apply the current screen rotation.
+                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
                 if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
-                    int tmp = dw;
+                    final int tmp = dw;
                     dw = dh;
                     dh = tmp;
                     rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
                 }
+
                 if (DEBUG_SCREENSHOT) {
                     Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
                             + maxLayer + " appToken=" + appToken);
@@ -5850,27 +5842,31 @@
                                 + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
                     }
                 }
-                // TODO: Replace 'false' in the following line with a variable that indicates
-                // whether the screenshot should use the identity transformation matrix
-                // (e.g., enable it when taking a screenshot for recents, since we might be in
-                // the middle of the rotation animation, but don't want a rotated recent image).
-                // TODO: Replace 'new Rect()' with the portion of the screen to capture for the
-                // screenshot.
-                rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false);
-            }
-        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
-        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
-                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
-                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
 
-        if (rawss == null) {
-            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
-                    + ") to layer " + maxLayer);
-            return null;
+                ScreenRotationAnimation screenRotationAnimation =
+                        mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+                final boolean inRotation = screenRotationAnimation != null &&
+                        screenRotationAnimation.isAnimating();
+                if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
+                        "Taking screenshot while rotating");
+
+                rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer,
+                        inRotation);
+                if (rawss == null) {
+                    Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
+                            + ") to layer " + maxLayer);
+                    return null;
+                }
+            }
+
+            break;
         }
 
-        Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
-        bm.eraseColor(0xFF000000);
+        Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
+                Config.RGB_565 : rawss.getConfig());
+        if (DEBUG_SCREENSHOT) {
+            bm.eraseColor(0xFF000000);
+        }
         frame.scale(scale);
         Matrix matrix = new Matrix();
         ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
@@ -11173,17 +11169,14 @@
         public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
             synchronized (mWindowMap) {
                 mWaitingForDrawnCallback = callback;
-                for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
-                    final WindowList windows =
-                            mDisplayContents.valueAt(displayNdx).getWindowList();
-                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                        final WindowState win = windows.get(winNdx);
-                        if (win.mHasSurface && win.isWinVisibleLw() && !win.mIsWallpaper) {
-                            win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
-                            // Force add to mResizingWindows.
-                            win.mLastContentInsets.set(-1, -1, -1, -1);
-                            mWaitingForDrawn.add(win);
-                        }
+                final WindowList windows = getDefaultWindowListLocked();
+                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                    final WindowState win = windows.get(winNdx);
+                    if (win.mHasSurface) {
+                        win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+                        // Force add to mResizingWindows.
+                        win.mLastContentInsets.set(-1, -1, -1, -1);
+                        mWaitingForDrawn.add(win);
                     }
                 }
                 requestTraversalLocked();
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 46af471..8bb6e8a 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -950,6 +950,15 @@
             receivedGpsTowSetterMethod,
             measurement->received_gps_tow_ns);
 
+    jmethodID receivedGpsTowUncertaintySetterMethod = env->GetMethodID(
+            gpsMeasurementClass,
+            "setReceivedGpsTowUncertaintyInNs",
+            longSignature);
+    env->CallVoidMethod(
+            gpsMeasurementObject,
+            receivedGpsTowUncertaintySetterMethod,
+            measurement->received_gps_tow_uncertainty_ns);
+
     jmethodID cn0SetterMethod =
             env->GetMethodID(gpsMeasurementClass, "setCn0InDbHz", doubleSignature);
     env->CallObjectMethod(gpsMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2a11252..5c661af 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1103,6 +1103,8 @@
             type = parser.next();
             int outerDepth = parser.getDepth();
             policy.mLockTaskPackages.clear();
+            policy.mAdminList.clear();
+            policy.mAdminMap.clear();
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -1124,7 +1126,6 @@
                             ActiveAdmin ap = new ActiveAdmin(dai);
                             ap.readFromXml(parser);
                             policy.mAdminMap.put(ap.info.getComponent(), ap);
-                            policy.mAdminList.add(ap);
                         }
                     } catch (RuntimeException e) {
                         Slog.w(LOG_TAG, "Failed loading admin " + name, e);
@@ -1184,6 +1185,9 @@
             // Ignore
         }
 
+        // Generate a list of admins from the admin map
+        policy.mAdminList.addAll(policy.mAdminMap.values());
+
         // Validate that what we stored for the password quality matches
         // sufficiently what is currently set.  Note that this is only
         // a sanity check in case the two get out of sync; this should
@@ -1268,10 +1272,8 @@
         if (!mHasFeature) {
             return;
         }
-        synchronized (this) {
-            loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER);
-            loadDeviceOwner();
-        }
+        getUserData(UserHandle.USER_OWNER);
+        loadDeviceOwner();
         cleanUpOldUsers();
         mAppOpsService = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -1436,14 +1438,12 @@
                 ActiveAdmin newAdmin = new ActiveAdmin(info);
                 policy.mAdminMap.put(adminReceiver, newAdmin);
                 int replaceIndex = -1;
-                if (refreshing) {
-                    final int N = policy.mAdminList.size();
-                    for (int i=0; i < N; i++) {
-                        ActiveAdmin oldAdmin = policy.mAdminList.get(i);
-                        if (oldAdmin.info.getComponent().equals(adminReceiver)) {
-                            replaceIndex = i;
-                            break;
-                        }
+                final int N = policy.mAdminList.size();
+                for (int i=0; i < N; i++) {
+                    ActiveAdmin oldAdmin = policy.mAdminList.get(i);
+                    if (oldAdmin.info.getComponent().equals(adminReceiver)) {
+                        replaceIndex = i;
+                        break;
                     }
                 }
                 if (replaceIndex == -1) {
@@ -2575,6 +2575,7 @@
                 return;
             }
             Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
+            intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
             intent.setComponent(admin.info.getComponent());
             mContext.sendOrderedBroadcastAsUser(intent, new UserHandle(userHandle),
                     null, new BroadcastReceiver() {
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 88aaafc..9e3dec8 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -162,12 +162,10 @@
         mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
         nextConnBroadcast.get();
 
-        // verify that both routes were added and DNS was flushed
+        // verify that both routes were added
         int mobileNetId = mMobile.tracker.getNetwork().netId;
         verify(mNetManager).addRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4));
         verify(mNetManager).addRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6));
-        verify(mNetManager).flushNetworkDnsCache(mobileNetId);
-
     }
 
     public void testMobileWifiHandoff() throws Exception {
@@ -204,7 +202,6 @@
         int wifiNetId = mWifi.tracker.getNetwork().netId;
         verify(mNetManager).addRoute(eq(wifiNetId), eq(WIFI_ROUTE_V4));
         verify(mNetManager).addRoute(eq(wifiNetId), eq(WIFI_ROUTE_V6));
-        verify(mNetManager).flushNetworkDnsCache(wifiNetId);
         verify(mMobile.tracker).teardown();
 
         int mobileNetId = mMobile.tracker.getNetwork().netId;
diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
new file mode 100644
index 0000000..3cc04e8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.server.notification;
+
+import android.app.Notification;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+
+public class RankingHelperTest extends AndroidTestCase {
+
+    private Notification mNotiGroupGSortA;
+    private Notification mNotiGroupGSortB;
+    private Notification mNotiNoGroup;
+    private Notification mNotiNoGroup2;
+    private Notification mNotiNoGroupSortA;
+    private NotificationRecord mRecordGroupGSortA;
+    private NotificationRecord mRecordGroupGSortB;
+    private NotificationRecord mRecordNoGroup;
+    private NotificationRecord mRecordNoGroup2;
+    private NotificationRecord mRecordNoGroupSortA;
+    private RankingHelper mHelper;
+
+    @Override
+    public void setUp() {
+        UserHandle user = UserHandle.ALL;
+
+        mHelper = new RankingHelper(getContext(), null, new String[0]);
+
+        mNotiGroupGSortA = new Notification.Builder(getContext())
+                .setContentTitle("A")
+                .setGroup("G")
+                .setSortKey("A")
+                .setWhen(1205)
+                .build();
+        mRecordGroupGSortA = new NotificationRecord(new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortA, user), 0);
+
+        mNotiGroupGSortB = new Notification.Builder(getContext())
+                .setContentTitle("B")
+                .setGroup("G")
+                .setSortKey("B")
+                .setWhen(1200)
+                .build();
+        mRecordGroupGSortB = new NotificationRecord(new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortB, user), 0);
+
+        mNotiNoGroup = new Notification.Builder(getContext())
+                .setContentTitle("C")
+                .setWhen(1201)
+                .build();
+        mRecordNoGroup = new NotificationRecord(new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup, user), 0);
+
+        mNotiNoGroup2 = new Notification.Builder(getContext())
+                .setContentTitle("D")
+                .setWhen(1202)
+                .build();
+        mRecordNoGroup2 = new NotificationRecord(new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup2, user), 0);
+
+        mNotiNoGroupSortA = new Notification.Builder(getContext())
+                .setContentTitle("E")
+                .setWhen(1201)
+                .setSortKey("A")
+                .build();
+        mRecordNoGroupSortA = new NotificationRecord(new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user), 0);
+    }
+
+    @SmallTest
+    public void testFindAfterRankingWithASplitGroup() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3);
+        notificationList.add(mRecordGroupGSortA);
+        notificationList.add(mRecordGroupGSortB);
+        notificationList.add(mRecordNoGroup);
+        notificationList.add(mRecordNoGroupSortA);
+        mHelper.sort(notificationList);
+        assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortA) >= 0);
+        assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortB) >= 0);
+        assertTrue(mHelper.indexOf(notificationList, mRecordNoGroup) >= 0);
+        assertTrue(mHelper.indexOf(notificationList, mRecordNoGroupSortA) >= 0);
+    }
+
+    @SmallTest
+    public void testSortShouldNotThrowWithPlainNotifications() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2);
+        notificationList.add(mRecordNoGroup);
+        notificationList.add(mRecordNoGroup2);
+        mHelper.sort(notificationList);
+    }
+
+    @SmallTest
+    public void testSortShouldNotThrowOneSorted() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2);
+        notificationList.add(mRecordNoGroup);
+        notificationList.add(mRecordNoGroupSortA);
+        mHelper.sort(notificationList);
+    }
+
+    @SmallTest
+    public void testSortShouldNotThrowOneNotification() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1);
+        notificationList.add(mRecordNoGroup);
+        mHelper.sort(notificationList);
+    }
+
+    @SmallTest
+    public void testSortShouldNotThrowOneSortKey() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1);
+        notificationList.add(mRecordGroupGSortB);
+        mHelper.sort(notificationList);
+    }
+
+    @SmallTest
+    public void testSortShouldNotThrowOnEmptyList() throws Exception {
+        ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>();
+        mHelper.sort(notificationList);
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 475824a..4018def 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -386,8 +386,8 @@
         private boolean hasPermission(String callingPackage) {
             final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
                     Binder.getCallingUid(), callingPackage);
-            if (mode == AppOpsManager.MODE_IGNORED) {
-                // If AppOpsManager ignores this, still allow if we have the system level
+            if (mode == AppOpsManager.MODE_DEFAULT) {
+                // The default behavior here is to check if PackageManager has given the app
                 // permission.
                 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
                         == PackageManager.PERMISSION_GRANTED;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index 50be1dc..1e0d6de 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -100,29 +100,32 @@
     }
 
     public boolean addOrUpdateKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
-        SQLiteDatabase db = getWritableDatabase();
-        ContentValues values = new ContentValues();
-        // Generate a random ID for the model.
-        values.put(SoundModelContract.KEY_ID, soundModel.uuid.toString());
-        values.put(SoundModelContract.KEY_DATA, soundModel.data);
-        values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
-
-        boolean status = true;
-        if (db.insertWithOnConflict(
-                SoundModelContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE) != -1) {
-            for (Keyphrase keyphrase : soundModel.keyphrases) {
-                status &= addOrUpdateKeyphrase(db, soundModel.uuid, keyphrase);
+        synchronized(this) {
+            SQLiteDatabase db = getWritableDatabase();
+            ContentValues values = new ContentValues();
+            // Generate a random ID for the model.
+            values.put(SoundModelContract.KEY_ID, soundModel.uuid.toString());
+            values.put(SoundModelContract.KEY_DATA, soundModel.data);
+            values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
+    
+            boolean status = true;
+            if (db.insertWithOnConflict(SoundModelContract.TABLE, null, values,
+                    SQLiteDatabase.CONFLICT_REPLACE) != -1) {
+                for (Keyphrase keyphrase : soundModel.keyphrases) {
+                    status &= addOrUpdateKeyphraseLocked(db, soundModel.uuid, keyphrase);
+                }
+                db.close();
+                return status;
+            } else {
+                Slog.w(TAG, "Failed to persist sound model to database");
+                db.close();
+                return false;
             }
-            db.close();
-            return status;
-        } else {
-            Slog.w(TAG, "Failed to persist sound model to database");
-            db.close();
-            return false;
         }
     }
 
-    private boolean addOrUpdateKeyphrase(SQLiteDatabase db, UUID modelId, Keyphrase keyphrase) {
+    private boolean addOrUpdateKeyphraseLocked(
+            SQLiteDatabase db, UUID modelId, Keyphrase keyphrase) {
         ContentValues values = new ContentValues();
         values.put(KeyphraseContract.KEY_ID, keyphrase.id);
         values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModes);
@@ -143,62 +146,66 @@
      * Deletes the sound model and associated keyphrases.
      */
     public boolean deleteKeyphraseSoundModel(UUID uuid) {
-        SQLiteDatabase db = getWritableDatabase();
-        String modelId = uuid.toString();
-        String soundModelClause = SoundModelContract.KEY_ID + "=" + modelId;
-        boolean status = true;
-        if (db.delete(SoundModelContract.TABLE, soundModelClause, null) == 0) {
-            Slog.w(TAG, "No sound models deleted from the database");
-            status = false;
+        synchronized(this) {
+            SQLiteDatabase db = getWritableDatabase();
+            String modelId = uuid.toString();
+            String soundModelClause = SoundModelContract.KEY_ID + "=" + modelId;
+            boolean status = true;
+            if (db.delete(SoundModelContract.TABLE, soundModelClause, null) == 0) {
+                Slog.w(TAG, "No sound models deleted from the database");
+                status = false;
+            }
+            String keyphraseClause = KeyphraseContract.KEY_SOUND_MODEL_ID + "=" + modelId;
+            if (db.delete(KeyphraseContract.TABLE, keyphraseClause, null) == 0) {
+                Slog.w(TAG, "No keyphrases deleted from the database");
+                status = false;
+            }
+            db.close();
+            return status;
         }
-        String keyphraseClause = KeyphraseContract.KEY_SOUND_MODEL_ID + "=" + modelId;
-        if (db.delete(KeyphraseContract.TABLE, keyphraseClause, null) == 0) {
-            Slog.w(TAG, "No keyphrases deleted from the database");
-            status = false;
-        }
-        db.close();
-        return status;
     }
 
     /**
      * Lists all the keyphrase sound models currently registered with the system.
      */
     public List<KeyphraseSoundModel> getKephraseSoundModels() {
-        List<KeyphraseSoundModel> models = new ArrayList<>();
-        String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE;
-        SQLiteDatabase db = getReadableDatabase();
-        Cursor c = db.rawQuery(selectQuery, null);
-
-        // looping through all rows and adding to list
-        if (c.moveToFirst()) {
-            do {
-                int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
-                if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
-                    // Ignore non-keyphrase sound models.
-                    continue;
-                }
-                String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID));
-                byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
-                // Get all the keyphrases for this this sound model.
-                // Validate the sound model.
-                if (id == null) {
-                    Slog.w(TAG, "Ignoring sound model since it doesn't specify an ID");
-                    continue;
-                }
-                KeyphraseSoundModel model = new KeyphraseSoundModel(
-                        UUID.fromString(id), data, getKeyphrasesForSoundModel(db, id));
-                if (DBG) {
-                    Slog.d(TAG, "Adding model: " + model);
-                }
-                models.add(model);
-            } while (c.moveToNext());
+        synchronized(this) {
+            List<KeyphraseSoundModel> models = new ArrayList<>();
+            String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE;
+            SQLiteDatabase db = getReadableDatabase();
+            Cursor c = db.rawQuery(selectQuery, null);
+    
+            // looping through all rows and adding to list
+            if (c.moveToFirst()) {
+                do {
+                    int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
+                    if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
+                        // Ignore non-keyphrase sound models.
+                        continue;
+                    }
+                    String id = c.getString(c.getColumnIndex(SoundModelContract.KEY_ID));
+                    byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
+                    // Get all the keyphrases for this this sound model.
+                    // Validate the sound model.
+                    if (id == null) {
+                        Slog.w(TAG, "Ignoring sound model since it doesn't specify an ID");
+                        continue;
+                    }
+                    KeyphraseSoundModel model = new KeyphraseSoundModel(
+                            UUID.fromString(id), data, getKeyphrasesForSoundModelLocked(db, id));
+                    if (DBG) {
+                        Slog.d(TAG, "Adding model: " + model);
+                    }
+                    models.add(model);
+                } while (c.moveToNext());
+            }
+            c.close();
+            db.close();
+            return models;
         }
-        c.close();
-        db.close();
-        return models;
     }
 
-    private Keyphrase[] getKeyphrasesForSoundModel(SQLiteDatabase db, String modelId) {
+    private Keyphrase[] getKeyphrasesForSoundModelLocked(SQLiteDatabase db, String modelId) {
         List<Keyphrase> keyphrases = new ArrayList<>();
         String selectQuery = "SELECT  * FROM " + KeyphraseContract.TABLE
                 + " WHERE " + KeyphraseContract.KEY_SOUND_MODEL_ID + " = '" + modelId + "'";
@@ -243,7 +250,7 @@
     }
 
 
-    private String getCommaSeparatedString(int[] users) {
+    private static String getCommaSeparatedString(int[] users) {
         if (users == null || users.length == 0) {
             return "";
         }
@@ -255,7 +262,7 @@
         return csv.substring(0, csv.length() - 1);
     }
 
-    private int[] getArrayForCommaSeparatedString(String text) {
+    private static int[] getArrayForCommaSeparatedString(String text) {
         if (TextUtils.isEmpty(text)) {
             return null;
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 2ce4971..5d9e107 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -266,13 +266,13 @@
                                 + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
                     }
                 }
+            }
 
-                final long caller = Binder.clearCallingIdentity();
-                try {
-                    return mDbHelper.getKephraseSoundModels();
-                } finally {
-                    Binder.restoreCallingIdentity(caller);
-                }
+            final long caller = Binder.clearCallingIdentity();
+            try {
+                return mDbHelper.getKephraseSoundModels();
+            } finally {
+                Binder.restoreCallingIdentity(caller);
             }
         }
 
@@ -287,26 +287,31 @@
                 if (model == null) {
                     throw new IllegalArgumentException("Model must not be null");
                 }
+            }
 
-                final long caller = Binder.clearCallingIdentity();
-                try {
+            final long caller = Binder.clearCallingIdentity();
+            try {
+                boolean success = false;
+                if (model.keyphrases == null) {
                     // If the keyphrases are not present in the model, delete the model.
-                    if (model.keyphrases == null) {
-                        if (mDbHelper.deleteKeyphraseSoundModel(model.uuid)) {
-                            return SoundTriggerHelper.STATUS_OK;
-                        } else {
-                            return SoundTriggerHelper.STATUS_ERROR;
-                        }
-                    } else {
-                        if (mDbHelper.addOrUpdateKeyphraseSoundModel(model)) {
-                            return SoundTriggerHelper.STATUS_OK;
-                        } else {
-                            return SoundTriggerHelper.STATUS_ERROR;
+                    success = mDbHelper.deleteKeyphraseSoundModel(model.uuid);
+                } else {
+                    // Else update the model.
+                    success = mDbHelper.addOrUpdateKeyphraseSoundModel(model);
+                }
+                if (success) {
+                    synchronized (this) {
+                        // Notify the voice interaction service of a change in sound models.
+                        if (mImpl != null && mImpl.mService != null) {
+                            mImpl.notifySoundModelsChangedLocked();
                         }
                     }
-                } finally {
-                    Binder.restoreCallingIdentity(caller);
+                    return SoundTriggerHelper.STATUS_OK;
+                } else {
+                    return SoundTriggerHelper.STATUS_ERROR;
                 }
+            } finally {
+                Binder.restoreCallingIdentity(caller);
             }
         }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 54af5d4..94f227c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -96,6 +96,13 @@
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
+            try {
+                if (mService != null) {
+                    mService.shutdown();
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "RemoteException in shutdown", e);
+            }
             mService = null;
         }
     };
@@ -308,4 +315,15 @@
             mContext.unregisterReceiver(mBroadcastReceiver);
         }
     }
+
+    void notifySoundModelsChangedLocked() {
+        if (mService == null) {
+            Slog.w(TAG, "Not bound to voice interaction service " + mComponent);
+        }
+        try {
+            mService.soundModelsChanged();
+        } catch (RemoteException e) {
+            Slog.w(TAG, "RemoteException while calling soundModelsChanged", e);
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/RemoteCallVideoClient.java b/telecomm/java/android/telecomm/RemoteCallVideoClient.java
index 8024831..08d1391 100644
--- a/telecomm/java/android/telecomm/RemoteCallVideoClient.java
+++ b/telecomm/java/android/telecomm/RemoteCallVideoClient.java
@@ -26,17 +26,20 @@
 /**
  * Remote class to invoke callbacks in InCallUI related to supporting video in calls.
  */
-public class RemoteCallVideoClient implements IBinder.DeathRecipient {
+public class RemoteCallVideoClient {
     private final ICallVideoClient mCallVideoClient;
 
+    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            mCallVideoClient.asBinder().unlinkToDeath(this, 0);
+        }
+    };
+
+    /** {@hide} */
     RemoteCallVideoClient(ICallVideoClient callVideoProvider) throws RemoteException {
         mCallVideoClient = callVideoProvider;
-        mCallVideoClient.asBinder().linkToDeath(this, 0);
-    }
-
-    @Override
-    public void binderDied() {
-        mCallVideoClient.asBinder().unlinkToDeath(this, 0);
+        mCallVideoClient.asBinder().linkToDeath(mDeathRecipient, 0);
     }
 
     /**
@@ -49,9 +52,11 @@
      *
      * @param videoCallProfile The requested video call profile.
      */
-    public void receiveSessionModifyRequest(VideoCallProfile videoCallProfile)
-            throws RemoteException {
-        mCallVideoClient.receiveSessionModifyRequest(videoCallProfile);
+    public void receiveSessionModifyRequest(VideoCallProfile videoCallProfile) {
+        try {
+            mCallVideoClient.receiveSessionModifyRequest(videoCallProfile);
+        } catch (RemoteException e) {
+        }
     }
 
     /**
@@ -66,9 +71,13 @@
      * @param requestedProfile The original request which was sent to the remote device.
      * @param responseProfile The actual profile changes made by the remote device.
      */
-    public void receiveSessionModifyResponse(int status, VideoCallProfile requestedProfile,
-            VideoCallProfile responseProfile) throws RemoteException {
-        mCallVideoClient.receiveSessionModifyResponse(status, requestedProfile, responseProfile);
+    public void receiveSessionModifyResponse(
+            int status, VideoCallProfile requestedProfile, VideoCallProfile responseProfile) {
+        try {
+            mCallVideoClient.receiveSessionModifyResponse(
+                    status, requestedProfile, responseProfile);
+        } catch (RemoteException e) {
+        }
     }
 
     /**
@@ -81,8 +90,11 @@
      *
      * @param event The event.
      */
-    public void handleCallSessionEvent(int event) throws RemoteException {
-        mCallVideoClient.handleCallSessionEvent(event);
+    public void handleCallSessionEvent(int event) {
+        try {
+            mCallVideoClient.handleCallSessionEvent(event);
+        } catch (RemoteException e) {
+        }
     }
 
     /**
@@ -92,8 +104,11 @@
      * @param width  The updated peer video width.
      * @param height The updated peer video height.
      */
-    public void updatePeerDimensions(int width, int height) throws RemoteException {
-        mCallVideoClient.updatePeerDimensions(width, height);
+    public void updatePeerDimensions(int width, int height) {
+        try {
+            mCallVideoClient.updatePeerDimensions(width, height);
+        } catch (RemoteException e) {
+        }
     }
 
     /**
@@ -101,8 +116,11 @@
      *
      * @param dataUsage The updated data usage.
      */
-    public void updateCallDataUsage(int dataUsage) throws RemoteException {
-        mCallVideoClient.updateCallDataUsage(dataUsage);
+    public void updateCallDataUsage(int dataUsage) {
+        try {
+            mCallVideoClient.updateCallDataUsage(dataUsage);
+        } catch (RemoteException e) {
+        }
     }
 
     /**
@@ -110,8 +128,10 @@
      *
      * @param callCameraCapabilities The changed camera capabilities.
      */
-    public void handleCameraCapabilitiesChange(CallCameraCapabilities callCameraCapabilities)
-            throws RemoteException {
-        mCallVideoClient.handleCameraCapabilitiesChange(callCameraCapabilities);
+    public void handleCameraCapabilitiesChange(CallCameraCapabilities callCameraCapabilities) {
+        try {
+            mCallVideoClient.handleCameraCapabilitiesChange(callCameraCapabilities);
+        } catch (RemoteException e) {
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/tests/MusicBrowserDemo/Android.mk b/tests/MusicBrowserDemo/Android.mk
new file mode 100644
index 0000000..207774b
--- /dev/null
+++ b/tests/MusicBrowserDemo/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := MusicBrowserDemo
+#LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-v4 \
+    android-support-v7-appcompat
+
+LOCAL_RESOURCE_DIR := \
+        $(LOCAL_PATH)/res \
+        frameworks/support/v7/appcompat/res
+LOCAL_PROGUARD_ENABLED := disabled
+#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_AAPT_FLAGS := \
+        --auto-add-overlay \
+        --extra-packages android.support.v7.appcompat
+include $(BUILD_PACKAGE)
diff --git a/tests/MusicBrowserDemo/AndroidManifest.xml b/tests/MusicBrowserDemo/AndroidManifest.xml
new file mode 100644
index 0000000..d2acfe2
--- /dev/null
+++ b/tests/MusicBrowserDemo/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.musicbrowserdemo"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme"
+        >
+
+        <activity
+            android:name="com.example.android.musicbrowserdemo.MainActivity"
+            android:label="@string/app_name"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+</manifest>
diff --git a/tests/MusicBrowserDemo/res/drawable-hdpi/ic_launcher.png b/tests/MusicBrowserDemo/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..47d6854
--- /dev/null
+++ b/tests/MusicBrowserDemo/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicBrowserDemo/res/drawable-mdpi/ic_launcher.png b/tests/MusicBrowserDemo/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..01b53fd
--- /dev/null
+++ b/tests/MusicBrowserDemo/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicBrowserDemo/res/drawable-xhdpi/ic_launcher.png b/tests/MusicBrowserDemo/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..af762f2
--- /dev/null
+++ b/tests/MusicBrowserDemo/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicBrowserDemo/res/drawable-xxhdpi/ic_launcher.png b/tests/MusicBrowserDemo/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..eef47aa
--- /dev/null
+++ b/tests/MusicBrowserDemo/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicBrowserDemo/res/values/strings.xml b/tests/MusicBrowserDemo/res/values/strings.xml
new file mode 100644
index 0000000..858f278f
--- /dev/null
+++ b/tests/MusicBrowserDemo/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<resources>
+
+    <string name="app_name">Music Browser</string>
+
+</resources>
diff --git a/tests/MusicBrowserDemo/res/values/styles.xml b/tests/MusicBrowserDemo/res/values/styles.xml
new file mode 100644
index 0000000..b83662d
--- /dev/null
+++ b/tests/MusicBrowserDemo/res/values/styles.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
new file mode 100644
index 0000000..c0f3a7f
--- /dev/null
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2010 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.example.android.musicbrowserdemo;
+
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.media.browse.MediaBrowserService;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.app.ListFragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// TODO: Include an icon.
+
+public class AppListFragment extends ListFragment {
+
+    private Adapter mAdapter;
+    private List<Item> mItems;
+
+    public AppListFragment() {
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mAdapter = new Adapter();
+        setListAdapter(mAdapter);
+    }
+
+    @Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        final Item item = mItems.get(position);
+
+        Log.i("AppListFragment", "Item clicked: " + position + " -- " + item.component);
+
+        final BrowserListFragment fragment = new BrowserListFragment();
+
+        final Bundle args = new Bundle();
+        args.putParcelable(BrowserListFragment.ARG_COMPONENT, item.component);
+        fragment.setArguments(args);
+
+        getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, fragment)
+                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+                .addToBackStack(null)
+                .commit();
+    }
+
+    private static class Item {
+        final String label;
+        final ComponentName component;
+
+        Item(String l, ComponentName c) {
+            this.label = l;
+            this.component = c;
+        }
+    }
+
+    private class Adapter extends BaseAdapter {
+        private final LayoutInflater mInflater;
+
+        Adapter() {
+            super();
+
+            final Context context = getActivity();
+            mInflater = LayoutInflater.from(context);
+
+            // Load the data
+            final PackageManager pm = context.getPackageManager();
+            final Intent intent = new Intent(MediaBrowserService.SERVICE_ACTION);
+            final List<ResolveInfo> list = pm.queryIntentServices(intent, 0);
+            final int N = list.size();
+            mItems = new ArrayList(N);
+            for (int i=0; i<N; i++) {
+                final ResolveInfo ri = list.get(i);
+                mItems.add(new Item(ri.loadLabel(pm).toString(), new ComponentName(
+                            ri.serviceInfo.applicationInfo.packageName,
+                            ri.serviceInfo.name)));
+            }
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public Item getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return 1;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
+            }
+
+            final TextView tv = (TextView)convertView;
+            final Item item = mItems.get(position);
+            tv.setText(item.label);
+
+            return convertView;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 1;
+        }
+    }
+}
+
+
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
new file mode 100644
index 0000000..3fc468d
--- /dev/null
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2010 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.example.android.musicbrowserdemo;
+
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+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.os.Bundle;
+import android.net.Uri;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.app.ListFragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BrowserListFragment extends ListFragment {
+    private static final String TAG = "BrowserListFragment";
+
+    // Hints
+    public static final String HINT_DISPLAY = "com.example.android.musicbrowserdemo.DISPLAY";
+
+    // For args
+    public static final String ARG_COMPONENT = "component";
+    public static final String ARG_URI = "uri";
+
+    private Adapter mAdapter;
+    private List<Item> mItems = new ArrayList();
+    private ComponentName mComponent;
+    private Uri mUri;
+    private MediaBrowser mBrowser;
+
+    private static class Item {
+        final MediaBrowserItem media;
+
+        Item(MediaBrowserItem m) {
+            this.media = m;
+        }
+    }
+
+    public BrowserListFragment() {
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        Log.d(TAG, "onActivityCreated -- " + hashCode());
+        mAdapter = new Adapter();
+        setListAdapter(mAdapter);
+
+        // Get our arguments
+        final Bundle args = getArguments();
+        mComponent = args.getParcelable(ARG_COMPONENT);
+        mUri = args.getParcelable(ARG_URI);
+
+        // A hint about who we are, so the service can customize the results if it wants to.
+        final Bundle rootHints = new Bundle();
+        rootHints.putBoolean(HINT_DISPLAY, true);
+
+        mBrowser = new MediaBrowser(getActivity(), mComponent, mConnectionCallbacks, rootHints);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mBrowser.connect();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mBrowser.disconnect();
+    }
+
+    @Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        final Item item = mItems.get(position);
+
+        Log.i("BrowserListFragment", "Item clicked: " + position + " -- "
+                + mAdapter.getItem(position).media.getUri());
+
+        final BrowserListFragment fragment = new BrowserListFragment();
+
+        final Bundle args = new Bundle();
+        args.putParcelable(BrowserListFragment.ARG_COMPONENT, mComponent);
+        args.putParcelable(BrowserListFragment.ARG_URI, item.media.getUri());
+        fragment.setArguments(args);
+
+        getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, fragment)
+                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+                .addToBackStack(null)
+                .commit();
+
+    }
+
+    final MediaBrowser.ConnectionCallback mConnectionCallbacks
+            = new MediaBrowser.ConnectionCallback() {
+        @Override
+        public void onConnected() {
+            Log.d(TAG, "mConnectionCallbacks.onConnected");
+            if (mUri == null) {
+                mUri = mBrowser.getRoot();
+            }
+            mBrowser.subscribe(mUri, new MediaBrowser.SubscriptionCallback() {
+                    @Override
+                    public void onChildrenLoaded(Uri parentUri, List<MediaBrowserItem> children) {
+                        Log.d(TAG, "onChildrenLoaded parentUri=" + parentUri
+                                + " children= " + children);
+                        mItems.clear();
+                        final int N = children.size();
+                        for (int i=0; i<N; i++) {
+                            mItems.add(new Item(children.get(i)));
+                        }
+                        mAdapter.notifyDataSetChanged();
+                    }
+
+                    @Override
+                    public void onError(Uri parentUri) {
+                        Log.d(TAG, "onError parentUri=" + parentUri);
+                    }
+                });
+        }
+
+        @Override
+        public void onConnectionSuspended() {
+            Log.d(TAG, "mConnectionCallbacks.onConnectionSuspended");
+        }
+
+        @Override
+        public void onConnectionFailed() {
+            Log.d(TAG, "mConnectionCallbacks.onConnectionFailed");
+        }
+    };
+
+    private class Adapter extends BaseAdapter {
+        private final LayoutInflater mInflater;
+
+        Adapter() {
+            super();
+
+            final Context context = getActivity();
+            mInflater = LayoutInflater.from(context);
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public Item getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return 1;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
+            }
+
+            final TextView tv = (TextView)convertView;
+            final Item item = mItems.get(position);
+            tv.setText(item.media.getTitle());
+
+            return convertView;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 1;
+        }
+    }
+}
+
+
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java
new file mode 100644
index 0000000..ed91aad
--- /dev/null
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 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.example.android.musicbrowserdemo;
+
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Main activity class.
+ */
+public class MainActivity extends FragmentActivity {
+
+    private static final String BROWSER_FRAGMENT_TAG = "browser";
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        Log.d("MainActivity", "-------------------------------------------------------");
+
+        // If we are starting afresh, start at the app list.
+        final FragmentManager fm = getSupportFragmentManager();
+        if (fm.findFragmentById(android.R.id.content) == null) {
+            fm.beginTransaction().add(android.R.id.content, new AppListFragment()).commit();
+        }
+    }
+}
+
diff --git a/tests/MusicServiceDemo/Android.mk b/tests/MusicServiceDemo/Android.mk
new file mode 100644
index 0000000..feef67a
--- /dev/null
+++ b/tests/MusicServiceDemo/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := MusicServiceDemo
+#LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-v4 \
+    android-support-v7-appcompat
+
+LOCAL_RESOURCE_DIR := \
+        $(LOCAL_PATH)/res \
+        frameworks/support/v7/appcompat/res
+LOCAL_PROGUARD_ENABLED := disabled
+#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_AAPT_FLAGS := \
+        --auto-add-overlay \
+        --extra-packages android.support.v7.appcompat
+include $(BUILD_PACKAGE)
diff --git a/tests/MusicServiceDemo/AndroidManifest.xml b/tests/MusicServiceDemo/AndroidManifest.xml
new file mode 100644
index 0000000..4178a80
--- /dev/null
+++ b/tests/MusicServiceDemo/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.musicservicedemo"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme"
+        >
+
+        <activity
+            android:name="com.example.android.automotive.musicplayer.MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <service
+            android:name=".BrowserService"
+            android:exported="true"
+            >
+            <intent-filter>
+                <action android:name="android.media.browse.MediaBrowseService" />
+            </intent-filter>
+        </service>
+    </application>
+
+</manifest>
diff --git a/tests/MusicServiceDemo/proguard-project.txt b/tests/MusicServiceDemo/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/tests/MusicServiceDemo/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..47d6854
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..01b53fd
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..af762f2
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..eef47aa
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.png b/tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.png
new file mode 100644
index 0000000..ea98c95
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/layout/activity_main.xml b/tests/MusicServiceDemo/res/layout/activity_main.xml
new file mode 100644
index 0000000..71753e3
--- /dev/null
+++ b/tests/MusicServiceDemo/res/layout/activity_main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.example.android.automotive.musicplayer.MainActivity"
+    tools:ignore="MergeRootFrame" />
diff --git a/tests/MusicServiceDemo/res/layout/fragment_main.xml b/tests/MusicServiceDemo/res/layout/fragment_main.xml
new file mode 100644
index 0000000..8796e86
--- /dev/null
+++ b/tests/MusicServiceDemo/res/layout/fragment_main.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context="com.example.android.automotive.musicplayer.MainActivity$PlaceholderFragment" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/app_name" />
+
+</RelativeLayout>
diff --git a/tests/MusicServiceDemo/res/values/colors.xml b/tests/MusicServiceDemo/res/values/colors.xml
new file mode 100644
index 0000000..44dd05d
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <color name="yellow">#ffffff00</color>
+    <color name="green">#ff00ff00</color>
+    <color name="blue">#ff0000ff</color>
+    <color name="red">#ffff0000</color>
+</resources>
diff --git a/tests/MusicServiceDemo/res/values/dimens.xml b/tests/MusicServiceDemo/res/values/dimens.xml
new file mode 100644
index 0000000..9f63ef2
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/tests/MusicServiceDemo/res/values/strings.xml b/tests/MusicServiceDemo/res/values/strings.xml
new file mode 100644
index 0000000..14c0171
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<resources>
+
+    <string name="app_name">Music Service Demo</string>
+    <string name="action_settings">Settings</string>
+    <string name="thumbs_up">Thumbs Up</string>
+    <string name="music_error">No music found</string>
+    <string name="now_playing">Now Playing</string>
+
+</resources>
diff --git a/tests/MusicServiceDemo/res/values/styles.xml b/tests/MusicServiceDemo/res/values/styles.xml
new file mode 100644
index 0000000..b83662d
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/styles.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
new file mode 100644
index 0000000..e5216b5
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.example.android.musicservicedemo;
+
+import android.app.SearchManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.UriMatcher;
+import android.content.res.Resources.NotFoundException;
+import android.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.media.AudioManager;
+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.session.MediaSession;
+import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.example.android.musicservicedemo.browser.MusicProvider;
+import com.example.android.musicservicedemo.browser.MusicProviderTask;
+import com.example.android.musicservicedemo.browser.MusicProviderTaskListener;
+import com.example.android.musicservicedemo.browser.MusicTrack;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service that implements MediaBrowserService and returns our menu hierarchy.
+ */
+public class BrowserService extends MediaBrowserService {
+    private static final String TAG = "BrowserService";
+
+    // URI paths for browsing music
+    public static final String BROWSE_ROOT_BASE_PATH = "browse";
+    public static final String NOW_PLAYING_PATH = "now_playing";
+    public static final String PIANO_BASE_PATH = "piano";
+    public static final String VOICE_BASE_PATH = "voice";
+
+    // Content URIs
+    public static final String AUTHORITY = "com.example.android.automotive.musicplayer";
+    public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);
+    public static final Uri BROWSE_URI = Uri.withAppendedPath(BASE_URI, BROWSE_ROOT_BASE_PATH);
+
+    // URI matcher constants for browsing paths
+    public static final int BROWSE_ROOT = 1;
+    public static final int NOW_PLAYING = 2;
+    public static final int PIANO = 3;
+    public static final int VOICE = 4;
+
+    // Map the the URI paths with the URI matcher constants
+    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+    static {
+        sUriMatcher.addURI(AUTHORITY, BROWSE_ROOT_BASE_PATH, BROWSE_ROOT);
+        sUriMatcher.addURI(AUTHORITY, NOW_PLAYING_PATH, NOW_PLAYING);
+        sUriMatcher.addURI(AUTHORITY, PIANO_BASE_PATH, PIANO);
+        sUriMatcher.addURI(AUTHORITY, VOICE_BASE_PATH, VOICE);
+    }
+
+    // Media metadata that will be provided for a media container
+    public static final String[] MEDIA_CONTAINER_PROJECTION = {
+            "uri",
+            "title",
+            "subtitle",
+            "image_uri",
+            "supported_actions"
+    };
+
+    // MusicProvider will download the music catalog
+    private MusicProvider mMusicProvider;
+
+    private MediaSession mSession;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        mSession = new MediaSession(this, "com.example.android.musicservicedemo.BrowserService");
+        setSessionToken(mSession.getSessionToken());
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+    }
+
+    @Override
+    protected BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
+        return new BrowserRoot(BROWSE_URI, null);
+    }
+
+    @Override
+    protected List<MediaBrowserItem> onLoadChildren(Uri parentUri) {
+        final ArrayList<MediaBrowserItem> results = new ArrayList();
+
+        for (int i=0; i<10; i++) {
+            results.add(new MediaBrowserItem.Builder(
+                    Uri.withAppendedPath(BASE_URI, Integer.toString(i)),
+                    MediaBrowserItem.FLAG_BROWSABLE, "Title " + i)
+                    .setSummary("Summary " + i)
+                    .build());
+        }
+
+        return results;
+    }
+
+    @Override
+    protected Bitmap onGetThumbnail(Uri uri, int width, int height) {
+        return null;
+    }
+
+    /*
+    @Override
+    public void query(final Query query, final IMetadataResultHandler metadataResultHandler,
+            final IErrorHandler errorHandler)
+            throws RemoteException {
+        Log.d(TAG, "query: " + query);
+        Utils.checkNotNull(query);
+        Utils.checkNotNull(metadataResultHandler);
+        Utils.checkNotNull(errorHandler);
+
+        // Handle async response
+        new Thread(new Runnable() {
+            public void run() {
+                try {
+                    // Pre-load the list of music
+                    List<MusicTrack> musicTracks = getMusicList();
+                    if (musicTracks == null) {
+                        notifyListenersOnPlaybackStateUpdate(getCurrentPlaybackState());
+                        errorHandler.onError(new Error(Error.UNKNOWN,
+                                getString(R.string.music_error)));
+                        return;
+                    }
+
+                    final Uri uri = query.getUri();
+                    int match = sUriMatcher.match(uri);
+                    Log.d(TAG, "Queried: " + uri + "; match: " + match);
+                    switch (match) {
+                        case BROWSE_ROOT:
+                        {
+                            Log.d(TAG, "Browse_root");
+
+                            try {
+                                MatrixCursor matrixCursor = mMusicProvider
+                                        .getRootContainerCurser();
+                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+                                        matrixCursor, null);
+
+                                Log.d(TAG, "on metadata response called " + holder.getCount());
+                                metadataResultHandler.onMetadataResponse(holder);
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Error delivering metadata in the callback.", e);
+                            }
+                            break;
+                        }
+                        case NOW_PLAYING:
+                        {
+                            try {
+                                Log.d(TAG, "query NOW_PLAYING");
+                                MatrixCursor matrixCursor = mMusicProvider
+                                        .getRootItemCursor(
+                                        PIANO);
+                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+                                        matrixCursor, null);
+                                Log.d(TAG, "on metadata response called " + holder.getCount());
+                                metadataResultHandler.onMetadataResponse(holder);
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Error querying NOW_PLAYING");
+                            }
+                            break;
+                        }
+                        case PIANO:
+                        {
+                            try {
+                                Log.d(TAG, "query PIANO");
+                                MatrixCursor matrixCursor = mMusicProvider
+                                        .getRootItemCursor(
+                                        PIANO);
+                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+                                        matrixCursor, null);
+                                Log.d(TAG, "on metadata response called " + holder.getCount());
+                                metadataResultHandler.onMetadataResponse(holder);
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Error querying PIANO");
+                            }
+                            break;
+                        }
+                        case VOICE:
+                        {
+                            try {
+                                Log.d(TAG, "query VOICE");
+                                MatrixCursor matrixCursor = mMusicProvider
+                                        .getRootItemCursor(
+                                        VOICE);
+                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+                                        matrixCursor, null);
+                                Log.d(TAG, "on metadata response called " + holder.getCount());
+                                metadataResultHandler.onMetadataResponse(holder);
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Error querying VOICE");
+                            }
+                            break;
+                        }
+                        default:
+                        {
+                            Log.w(TAG, "Skipping unmatched URI: " + uri);
+                        }
+                    }
+                } catch (NotFoundException e) {
+                    Log.e(TAG, "::run:", e);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "::run:", e);
+                }
+            } // end run
+        }).start();
+    }
+
+    */
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
new file mode 100644
index 0000000..db45b9d
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
@@ -0,0 +1,101 @@
+/* Copyright 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.example.android.musicservicedemo;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBarActivity;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.example.android.musicservicedemo.R;
+
+// TODO Local UI
+
+/**
+ * Main activity of the app.
+ */
+public class MainActivity extends ActionBarActivity {
+
+    private static final String LOG = "MainActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        if (savedInstanceState == null) {
+            getSupportFragmentManager().beginTransaction()
+                    .add(R.id.container, new PlaceholderFragment())
+                    .commit();
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
+     */
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+
+        // Inflate the menu; this adds items to the action bar if it is present.
+        //getMenuInflater().inflate(R.menu.main, menu);
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
+     */
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle action bar item clicks here. The action bar will
+        // automatically handle clicks on the Home/Up button, so long
+        // as you specify a parent activity in AndroidManifest.xml.
+        int id = item.getItemId();
+        // if (id == R.id.action_settings) {
+        // return true;
+        // }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     * A placeholder fragment containing a simple view.
+     */
+    public static class PlaceholderFragment extends Fragment {
+
+        public PlaceholderFragment() {
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater
+         * , android.view.ViewGroup, android.os.Bundle)
+         */
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
+            return rootView;
+        }
+    }
+
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java
new file mode 100644
index 0000000..3589761
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.example.android.musicservicedemo;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class Utils {
+
+    private static final String TAG = "Utils";
+
+    /**
+     * Utility method to check that parameters are not null
+     *
+     * @param object
+     */
+    public static final void checkNotNull(Object object) {
+        if (object == null) {
+            throw new NullPointerException();
+        }
+    }
+
+    /**
+     * Utility to download a bitmap
+     *
+     * @param source
+     * @return
+     */
+    public static Bitmap getBitmapFromURL(String source) {
+        try {
+            URL url = new URL(source);
+            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
+            httpConnection.setDoInput(true);
+            httpConnection.connect();
+            InputStream inputStream = httpConnection.getInputStream();
+            return BitmapFactory.decodeStream(inputStream);
+        } catch (IOException e) {
+            Log.e(TAG, "getBitmapFromUrl: " + source, e);
+        }
+        return null;
+    }
+
+    /**
+     * Utility method to wrap an index
+     *
+     * @param i
+     * @param size
+     * @return
+     */
+    public static int wrapIndex(int i, int size) {
+        int m = i % size;
+        if (m < 0) { // java modulus can be negative
+            m += size;
+        }
+        return m;
+    }
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java
new file mode 100644
index 0000000..15038d7
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.example.android.musicservicedemo.browser;
+
+import android.database.MatrixCursor;
+import android.media.session.PlaybackState;
+import android.net.Uri;
+import android.util.Log;
+
+import com.example.android.musicservicedemo.BrowserService;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class to get a list of MusicTrack's based on a server-side JSON
+ * configuration.
+ */
+public class MusicProvider {
+
+    private static final String TAG = "MusicProvider";
+
+    private static final String MUSIC_URL = "http://storage.googleapis.com/automotive-media/music.json";
+
+    private static String MUSIC = "music";
+    private static String TITLE = "title";
+    private static String ALBUM = "album";
+    private static String ARTIST = "artist";
+    private static String GENRE = "genre";
+    private static String SOURCE = "source";
+    private static String IMAGE = "image";
+    private static String TRACK_NUMBER = "trackNumber";
+    private static String TOTAL_TRACK_COUNT = "totalTrackCount";
+    private static String DURATION = "duration";
+
+    // Cache for music track data
+    private static List<MusicTrack> mMusicList;
+
+    /**
+     * Get the cached list of music tracks
+     *
+     * @return
+     * @throws JSONException
+     */
+    public List<MusicTrack> getMedia() throws JSONException {
+        if (null != mMusicList && mMusicList.size() > 0) {
+            return mMusicList;
+        }
+        return null;
+    }
+
+    /**
+     * Get the list of music tracks from a server and return the list of
+     * MusicTrack objects.
+     *
+     * @return
+     * @throws JSONException
+     */
+    public List<MusicTrack> retreiveMedia() throws JSONException {
+        if (null != mMusicList) {
+            return mMusicList;
+        }
+        int slashPos = MUSIC_URL.lastIndexOf('/');
+        String path = MUSIC_URL.substring(0, slashPos + 1);
+        JSONObject jsonObj = parseUrl(MUSIC_URL);
+
+        try {
+            JSONArray videos = jsonObj.getJSONArray(MUSIC);
+            if (null != videos) {
+                mMusicList = new ArrayList<MusicTrack>();
+                for (int j = 0; j < videos.length(); j++) {
+                    JSONObject music = videos.getJSONObject(j);
+                    String title = music.getString(TITLE);
+                    String album = music.getString(ALBUM);
+                    String artist = music.getString(ARTIST);
+                    String genre = music.getString(GENRE);
+                    String source = music.getString(SOURCE);
+                    // Media is stored relative to JSON file
+                    if (!source.startsWith("http")) {
+                        source = path + source;
+                    }
+                    String image = music.getString(IMAGE);
+                    if (!image.startsWith("http")) {
+                        image = path + image;
+                    }
+                    int trackNumber = music.getInt(TRACK_NUMBER);
+                    int totalTrackCount = music.getInt(TOTAL_TRACK_COUNT);
+                    int duration = music.getInt(DURATION) * 1000; // ms
+
+                    mMusicList.add(new MusicTrack(title, album, artist, genre, source,
+                            image, trackNumber, totalTrackCount, duration));
+                }
+            }
+        } catch (NullPointerException e) {
+            Log.e(TAG, "retreiveMedia", e);
+        }
+        return mMusicList;
+    }
+
+    /**
+     * Download a JSON file from a server, parse the content and return the JSON
+     * object.
+     *
+     * @param urlString
+     * @return
+     */
+    private JSONObject parseUrl(String urlString) {
+        InputStream is = null;
+        try {
+            java.net.URL url = new java.net.URL(urlString);
+            URLConnection urlConnection = url.openConnection();
+            is = new BufferedInputStream(urlConnection.getInputStream());
+            BufferedReader reader = new BufferedReader(new InputStreamReader(
+                    urlConnection.getInputStream(), "iso-8859-1"), 8);
+            StringBuilder sb = new StringBuilder();
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+            return new JSONObject(sb.toString());
+        } catch (Exception e) {
+            Log.d(TAG, "Failed to parse the json for media list", e);
+            return null;
+        } finally {
+            if (null != is) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+        }
+    }
+
+    public MatrixCursor getRootContainerCurser() {
+        MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+        Uri.Builder pianoBuilder = new Uri.Builder();
+        pianoBuilder.authority(BrowserService.AUTHORITY);
+        pianoBuilder.appendPath(BrowserService.PIANO_BASE_PATH);
+        matrixCursor.addRow(new Object[] {
+                pianoBuilder.build(),
+                BrowserService.PIANO_BASE_PATH,
+                "subtitle",
+                null,
+                0
+        });
+
+        Uri.Builder voiceBuilder = new Uri.Builder();
+        voiceBuilder.authority(BrowserService.AUTHORITY);
+        voiceBuilder.appendPath(BrowserService.VOICE_BASE_PATH);
+        matrixCursor.addRow(new Object[] {
+                voiceBuilder.build(),
+                BrowserService.VOICE_BASE_PATH,
+                "subtitle",
+                null,
+                0
+        });
+        return matrixCursor;
+    }
+
+    public MatrixCursor getRootItemCursor(int type) {
+        if (type == BrowserService.NOW_PLAYING) {
+            MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+
+            try {
+                // Just return all of the tracks for now
+                List<MusicTrack> musicTracks = retreiveMedia();
+                for (MusicTrack musicTrack : musicTracks) {
+                    Uri.Builder builder = new Uri.Builder();
+                    builder.authority(BrowserService.AUTHORITY);
+                    builder.appendPath(BrowserService.NOW_PLAYING_PATH);
+                    builder.appendPath(musicTrack.getTitle());
+                    matrixCursor.addRow(new Object[] {
+                            builder.build(),
+                            musicTrack.getTitle(),
+                            musicTrack.getArtist(),
+                            musicTrack.getImage(),
+                            PlaybackState.ACTION_PLAY
+                    });
+                    Log.d(TAG, "Uri " + builder.build());
+                }
+            } catch (JSONException e) {
+                Log.e(TAG, "::getRootItemCursor:", e);
+            }
+
+            Log.d(TAG, "cursor: " + matrixCursor.getCount());
+            return matrixCursor;
+        } else if (type == BrowserService.PIANO) {
+            MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+
+            try {
+                List<MusicTrack> musicTracks = retreiveMedia();
+                for (MusicTrack musicTrack : musicTracks) {
+                    Uri.Builder builder = new Uri.Builder();
+                    builder.authority(BrowserService.AUTHORITY);
+                    builder.appendPath(BrowserService.PIANO_BASE_PATH);
+                    builder.appendPath(musicTrack.getTitle());
+                    matrixCursor.addRow(new Object[] {
+                            builder.build(),
+                            musicTrack.getTitle(),
+                            musicTrack.getArtist(),
+                            musicTrack.getImage(),
+                            PlaybackState.ACTION_PLAY
+                    });
+                    Log.d(TAG, "Uri " + builder.build());
+                }
+            } catch (JSONException e) {
+                Log.e(TAG, "::getRootItemCursor:", e);
+            }
+
+            Log.d(TAG, "cursor: " + matrixCursor.getCount());
+            return matrixCursor;
+        } else if (type == BrowserService.VOICE) {
+            MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+
+            try {
+                List<MusicTrack> musicTracks = retreiveMedia();
+                for (MusicTrack musicTrack : musicTracks) {
+                    Uri.Builder builder = new Uri.Builder();
+                    builder.authority(BrowserService.AUTHORITY);
+                    builder.appendPath(BrowserService.VOICE_BASE_PATH);
+                    builder.appendPath(musicTrack.getTitle());
+                    matrixCursor.addRow(new Object[] {
+                            builder.build(),
+                            musicTrack.getTitle(),
+                            musicTrack.getArtist(),
+                            musicTrack.getImage(),
+                            PlaybackState.ACTION_PLAY
+                    });
+                    Log.d(TAG, "Uri " + builder.build());
+                }
+            } catch (JSONException e) {
+                Log.e(TAG, "::getRootItemCursor:", e);
+            }
+
+            Log.d(TAG, "cursor: " + matrixCursor.getCount());
+            return matrixCursor;
+
+        }
+        return null;
+    }
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java
new file mode 100644
index 0000000..ffda110
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java
@@ -0,0 +1,70 @@
+/*  
+ * 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.example.android.musicservicedemo.browser;
+
+import android.os.AsyncTask;
+import android.util.Log;
+
+import org.json.JSONException;
+
+/**
+ * Asynchronous task to retrieve the music data using MusicProvider.
+ */
+public class MusicProviderTask extends AsyncTask<Void, Void, Void> {
+
+    private static final String TAG = "MusicProviderTask";
+
+    MusicProvider mMusicProvider;
+    MusicProviderTaskListener mMusicProviderTaskListener;
+
+    /**
+     * Initialize the task with the provider to download the music data and the
+     * listener to be informed when the task is done.
+     *
+     * @param musicProvider
+     * @param listener
+     */
+    public MusicProviderTask(MusicProvider musicProvider,
+            MusicProviderTaskListener listener) {
+        mMusicProvider = musicProvider;
+        mMusicProviderTaskListener = listener;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see android.os.AsyncTask#doInBackground(java.lang.Object[])
+     */
+    @Override
+    protected Void doInBackground(Void... arg0) {
+        try {
+            mMusicProvider.retreiveMedia();
+        } catch (JSONException e) {
+            Log.e(TAG, "::doInBackground:", e);
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
+     */
+    @Override
+    protected void onPostExecute(Void result) {
+        mMusicProviderTaskListener.onMusicProviderTaskCompleted();
+    }
+
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java
new file mode 100644
index 0000000..b1d168f
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.example.android.musicservicedemo.browser;
+
+/**
+ * Callback listener for completion of MusicProviderTask
+ */
+public interface MusicProviderTaskListener {
+    public void onMusicProviderTaskCompleted();
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java
new file mode 100644
index 0000000..02ea899
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.example.android.musicservicedemo.browser;
+
+/**
+ * A class to model music track metadata.
+ */
+public class MusicTrack {
+
+    private static final String TAG = "MusicTrack";
+
+    private String mTitle;
+    private String mAlbum;
+    private String mArtist;
+    private String mGenre;
+    private String mSource;
+    private String mImage;
+    private int mTrackNumber;
+    private int mTotalTrackCount;
+    private int mDuration;
+
+    /**
+     * Constructor creating a MusicTrack instance.
+     *
+     * @param title
+     * @param album
+     * @param artist
+     * @param genre
+     * @param source
+     * @param image
+     * @param trackNumber
+     * @param totalTrackCount
+     * @param duration
+     */
+    public MusicTrack(String title, String album, String artist, String genre, String source,
+            String image, int trackNumber, int totalTrackCount, int duration) {
+        this.mTitle = title;
+        this.mAlbum = album;
+        this.mArtist = artist;
+        this.mGenre = genre;
+        this.mSource = source;
+        this.mImage = image;
+        this.mTrackNumber = trackNumber;
+        this.mTotalTrackCount = totalTrackCount;
+        this.mDuration = duration;
+    }
+
+    public String getTitle() {
+        return mTitle;
+    }
+
+    public void setTitle(String mTitle) {
+        this.mTitle = mTitle;
+    }
+
+    public String getAlbum() {
+        return mAlbum;
+    }
+
+    public void setAlbum(String mAlbum) {
+        this.mAlbum = mAlbum;
+    }
+
+    public String getArtist() {
+        return mArtist;
+    }
+
+    public void setArtist(String mArtist) {
+        this.mArtist = mArtist;
+    }
+
+    public String getGenre() {
+        return mGenre;
+    }
+
+    public void setGenre(String mGenre) {
+        this.mGenre = mGenre;
+    }
+
+    public String getSource() {
+        return mSource;
+    }
+
+    public void setSource(String mSource) {
+        this.mSource = mSource;
+    }
+
+    public String getImage() {
+        return mImage;
+    }
+
+    public void setImage(String mImage) {
+        this.mImage = mImage;
+    }
+
+    public int getTrackNumber() {
+        return mTrackNumber;
+    }
+
+    public void setTrackNumber(int mTrackNumber) {
+        this.mTrackNumber = mTrackNumber;
+    }
+
+    public int getTotalTrackCount() {
+        return mTotalTrackCount;
+    }
+
+    public void setTotalTrackCount(int mTotalTrackCount) {
+        this.mTotalTrackCount = mTotalTrackCount;
+    }
+
+    public int getDuration() {
+        return mDuration;
+    }
+
+    public void setDuration(int mDuration) {
+        this.mDuration = mDuration;
+    }
+
+    public String toString() {
+        return mTitle;
+    }
+
+}
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
new file mode 100644
index 0000000..69fefeb
--- /dev/null
+++ b/tests/UsageStatsTest/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := UsageStatsTest
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/AndroidManifest.xml b/tests/UsageStatsTest/AndroidManifest.xml
new file mode 100644
index 0000000..fac5810
--- /dev/null
+++ b/tests/UsageStatsTest/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.usagestats">
+
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+
+    <application android:label="Usage Access Test">
+        <activity android:name=".UsageStatsActivity"
+                  android:label="Device Usage History">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/UsageStatsTest/res/layout/row_item.xml b/tests/UsageStatsTest/res/layout/row_item.xml
new file mode 100644
index 0000000..da50163
--- /dev/null
+++ b/tests/UsageStatsTest/res/layout/row_item.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp">
+
+    <TextView android:id="@android:id/text1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentLeft="true"
+        android:layout_centerVertical="true"
+        android:textStyle="bold"/>
+
+    <TextView android:id="@android:id/text2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_alignBaseline="@android:id/text1"/>
+</RelativeLayout>
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
new file mode 100644
index 0000000..73143c5
--- /dev/null
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -0,0 +1,128 @@
+/*
+ * 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.tests.usagestats;
+
+import android.app.ListActivity;
+import android.app.usage.PackageUsageStats;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.format.DateUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class UsageStatsActivity extends ListActivity {
+
+    private UsageStatsManager mUsageStatsManager;
+    private Adapter mAdapter;
+    private Comparator<PackageUsageStats> mComparator = new Comparator<PackageUsageStats>() {
+        @Override
+        public int compare(PackageUsageStats o1, PackageUsageStats o2) {
+            return Long.compare(o2.getTotalTimeSpent(), o1.getTotalTimeSpent());
+        }
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
+        mAdapter = new Adapter();
+        updateAdapter();
+        setListAdapter(mAdapter);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        updateAdapter();
+    }
+
+    private void updateAdapter() {
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.DAY_OF_YEAR, -14);
+        UsageStats stats = mUsageStatsManager.getRecentStatsSince(cal.getTimeInMillis());
+        mAdapter.update(stats);
+    }
+
+    private class Adapter extends BaseAdapter {
+        private ArrayList<PackageUsageStats> mStats = new ArrayList<>();
+
+        public void update(UsageStats stats) {
+            mStats.clear();
+            if (stats == null) {
+                return;
+            }
+
+            final int packageCount = stats.getPackageCount();
+            for (int i = 0; i < packageCount; i++) {
+                mStats.add(stats.getPackage(i));
+            }
+
+            Collections.sort(mStats, mComparator);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mStats.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mStats.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final ViewHolder holder;
+            if (convertView == null) {
+                convertView = LayoutInflater.from(UsageStatsActivity.this)
+                        .inflate(R.layout.row_item, parent, false);
+                holder = new ViewHolder();
+                holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
+                holder.usageTime = (TextView) convertView.findViewById(android.R.id.text2);
+                convertView.setTag(holder);
+            } else {
+                holder = (ViewHolder) convertView.getTag();
+            }
+
+            holder.packageName.setText(mStats.get(position).getPackageName());
+            holder.usageTime.setText(DateUtils.formatDuration(
+                    mStats.get(position).getTotalTimeSpent()));
+            return convertView;
+        }
+    }
+
+    private static class ViewHolder {
+        TextView packageName;
+        TextView usageTime;
+    }
+}
\ No newline at end of file
diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml
index 33f000d..c328b3c 100644
--- a/tests/VoiceInteraction/AndroidManifest.xml
+++ b/tests/VoiceInteraction/AndroidManifest.xml
@@ -1,6 +1,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.test.voiceinteraction">
 
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+
     <application>
         <activity android:name="VoiceInteractionMain" android:label="Voice Interaction"
                 android:theme="@android:style/Theme.Material">
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index e74307f..cc710f9 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -30,6 +30,12 @@
 
     private final Callback mHotwordCallback = new Callback() {
         @Override
+        public void onAvailabilityChanged(int status) {
+            Log.i(TAG, "onAvailabilityChanged(" + status + ")");
+            hotwordAvailabilityChangeHelper(status);
+        }
+
+        @Override
         public void onDetected(byte[] data) {
             Log.i(TAG, "onDetected");
         }
@@ -50,30 +56,7 @@
         Log.i(TAG, "Keyphrase enrollment meta-data: "
                 + Arrays.toString(getKeyphraseEnrollmentInfo().listKeyphraseMetadata()));
 
-        mHotwordDetector = getAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback);
-        int availability = mHotwordDetector.getAvailability();
-        Log.i(TAG, "Hotword availability = " + availability);
-
-        switch (availability) {
-            case AlwaysOnHotwordDetector.KEYPHRASE_HARDWARE_UNAVAILABLE:
-                Log.i(TAG, "KEYPHRASE_HARDWARE_UNAVAILABLE");
-                break;
-            case AlwaysOnHotwordDetector.KEYPHRASE_UNSUPPORTED:
-                Log.i(TAG, "KEYPHRASE_UNSUPPORTED");
-                break;
-            case AlwaysOnHotwordDetector.KEYPHRASE_UNENROLLED:
-                Log.i(TAG, "KEYPHRASE_UNENROLLED");
-                Intent enroll = mHotwordDetector.getManageIntent(
-                        AlwaysOnHotwordDetector.MANAGE_ACTION_ENROLL);
-                Log.i(TAG, "Need to enroll with " + enroll);
-                break;
-            case AlwaysOnHotwordDetector.KEYPHRASE_ENROLLED:
-                Log.i(TAG, "KEYPHRASE_ENROLLED");
-                int status = mHotwordDetector.startRecognition(
-                        AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE);
-                Log.i(TAG, "startRecognition status = " + status);
-                break;
-        }
+        mHotwordDetector = createAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback);
     }
 
     @Override
@@ -84,4 +67,33 @@
         stopSelf(startId);
         return START_NOT_STICKY;
     }
+
+    private void hotwordAvailabilityChangeHelper(int availability) {
+        Log.i(TAG, "Hotword availability = " + availability);
+        switch (availability) {
+            case AlwaysOnHotwordDetector.STATE_INVALID:
+                Log.i(TAG, "STATE_INVALID");
+                mHotwordDetector =
+                        createAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback);
+                break;
+            case AlwaysOnHotwordDetector.STATE_HARDWARE_UNAVAILABLE:
+                Log.i(TAG, "STATE_HARDWARE_UNAVAILABLE");
+                break;
+            case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNSUPPORTED:
+                Log.i(TAG, "STATE_KEYPHRASE_UNSUPPORTED");
+                break;
+            case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
+                Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
+                Intent enroll = mHotwordDetector.getManageIntent(
+                        AlwaysOnHotwordDetector.MANAGE_ACTION_ENROLL);
+                Log.i(TAG, "Need to enroll with " + enroll);
+                break;
+            case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
+                Log.i(TAG, "STATE_KEYPHRASE_ENROLLED");
+                int status = mHotwordDetector.startRecognition(
+                        AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE);
+                Log.i(TAG, "startRecognition status = " + status);
+                break;
+        }
+    }
 }