Merge "Import translations. DO NOT MERGE"
diff --git a/Android.mk b/Android.mk
index 2f3a990..642d8b9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -217,14 +217,6 @@
 	core/java/android/service/wallpaper/IWallpaperConnection.aidl \
 	core/java/android/service/wallpaper/IWallpaperEngine.aidl \
 	core/java/android/service/wallpaper/IWallpaperService.aidl \
-	core/java/android/tv/ITvInputClient.aidl \
-	core/java/android/tv/ITvInputHardware.aidl \
-	core/java/android/tv/ITvInputHardwareCallback.aidl \
-	core/java/android/tv/ITvInputManager.aidl \
-	core/java/android/tv/ITvInputService.aidl \
-	core/java/android/tv/ITvInputServiceCallback.aidl \
-	core/java/android/tv/ITvInputSession.aidl \
-	core/java/android/tv/ITvInputSessionCallback.aidl \
 	core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
 	core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
 	core/java/android/view/accessibility/IAccessibilityManager.aidl \
@@ -322,6 +314,14 @@
         media/java/android/media/session/ISession.aidl \
         media/java/android/media/session/ISessionCallback.aidl \
         media/java/android/media/session/ISessionManager.aidl \
+	media/java/android/media/tv/ITvInputClient.aidl \
+	media/java/android/media/tv/ITvInputHardware.aidl \
+	media/java/android/media/tv/ITvInputHardwareCallback.aidl \
+	media/java/android/media/tv/ITvInputManager.aidl \
+	media/java/android/media/tv/ITvInputService.aidl \
+	media/java/android/media/tv/ITvInputServiceCallback.aidl \
+	media/java/android/media/tv/ITvInputSession.aidl \
+	media/java/android/media/tv/ITvInputSessionCallback.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallService.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 48a20a4..f3bb9b6 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -192,6 +192,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/wearable)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/ITv*)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index b059841..e669bf1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -708,7 +708,6 @@
     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_pad27 = 16843766; // 0x10103f6
     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
@@ -1022,6 +1021,7 @@
     field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
     field public static final int sessionService = 16843841; // 0x1010441
     field public static final int settingsActivity = 16843301; // 0x1010225
+    field public static final int setupActivity = 16843766; // 0x10103f6
     field public static final int shadowColor = 16843105; // 0x1010161
     field public static final int shadowDx = 16843106; // 0x1010162
     field public static final int shadowDy = 16843107; // 0x1010163
@@ -5246,6 +5246,7 @@
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
     field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "defaultManagedProfileName";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "deviceAdminPackageName";
+    field public static final java.lang.String EXTRA_PROVISIONING_TOKEN = "android.app.extra.token";
     field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
     field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
     field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
@@ -11271,14 +11272,11 @@
     method public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
     method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String);
     method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options);
-    method public static android.graphics.drawable.Drawable createFromResourceStreamThemed(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.content.res.Resources.Theme);
-    method public static android.graphics.drawable.Drawable createFromResourceStreamThemed(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options, android.content.res.Resources.Theme);
     method public static android.graphics.drawable.Drawable createFromStream(java.io.InputStream, java.lang.String);
-    method public static android.graphics.drawable.Drawable createFromStreamThemed(java.io.InputStream, java.lang.String, android.content.res.Resources.Theme);
     method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static android.graphics.drawable.Drawable createFromXmlInnerThemed(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
-    method public static android.graphics.drawable.Drawable createFromXmlThemed(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public abstract void draw(android.graphics.Canvas);
     method public int getAlpha();
     method public final android.graphics.Rect getBounds();
@@ -11554,7 +11552,6 @@
     method public android.graphics.Paint getPaint();
     method public android.graphics.drawable.ShapeDrawable.ShaderFactory getShaderFactory();
     method public android.graphics.drawable.shapes.Shape getShape();
-    method public android.content.res.ColorStateList getTint();
     method protected boolean inflateTag(java.lang.String, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
     method protected void onDraw(android.graphics.drawable.shapes.Shape, android.graphics.Canvas, android.graphics.Paint);
     method public void setAlpha(int);
@@ -11565,7 +11562,6 @@
     method public void setPadding(android.graphics.Rect);
     method public void setShaderFactory(android.graphics.drawable.ShapeDrawable.ShaderFactory);
     method public void setShape(android.graphics.drawable.shapes.Shape);
-    method public void setTint(android.content.res.ColorStateList);
   }
 
   public static abstract class ShapeDrawable.ShaderFactory {
@@ -15978,6 +15974,180 @@
 
 }
 
+package android.media.tv {
+
+  public final class TvContract {
+    method public static final android.net.Uri buildChannelUri(long);
+    method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName);
+    method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName, boolean);
+    method public static final android.net.Uri buildProgramUri(long);
+    method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri);
+    method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
+    field public static final java.lang.String AUTHORITY = "android.media.tv";
+  }
+
+  public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
+    field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
+  }
+
+  public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_DESCRIPTION = "description";
+    field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
+    field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
+    field public static final java.lang.String COLUMN_SERVICE_NAME = "service_name";
+    field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
+    field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    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 = 263168; // 0x40400
+    field public static final int TYPE_ATSC_C = 197120; // 0x30200
+    field public static final int TYPE_ATSC_M_H = 197120; // 0x30200
+    field public static final int TYPE_ATSC_T = 196608; // 0x30000
+    field public static final int TYPE_CMMB = 327936; // 0x50100
+    field public static final int TYPE_DTMB = 327680; // 0x50000
+    field public static final int TYPE_DVB_C = 131584; // 0x20200
+    field public static final int TYPE_DVB_C2 = 131585; // 0x20201
+    field public static final int TYPE_DVB_H = 131840; // 0x20300
+    field public static final int TYPE_DVB_S = 131328; // 0x20100
+    field public static final int TYPE_DVB_S2 = 131329; // 0x20101
+    field public static final int TYPE_DVB_SH = 132096; // 0x20400
+    field public static final int TYPE_DVB_T = 131072; // 0x20000
+    field public static final int TYPE_DVB_T2 = 131073; // 0x20001
+    field public static final int TYPE_ISDB_C = 262912; // 0x40300
+    field public static final int TYPE_ISDB_S = 262656; // 0x40200
+    field public static final int TYPE_ISDB_T = 262144; // 0x40000
+    field public static final int TYPE_ISDB_TB = 262400; // 0x40100
+    field public static final int TYPE_OTHER = 0; // 0x0
+    field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
+    field public static final int TYPE_S_DMB = 393472; // 0x60100
+    field public static final int TYPE_T_DMB = 393216; // 0x60000
+  }
+
+  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    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_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_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static final class TvContract.Programs.Genres {
+    method public static java.lang.String[] decode(java.lang.String);
+    method public static java.lang.String encode(java.lang.String...);
+    field public static final java.lang.String ANIMAL_WILDLIFE = "Animal/Wildlife";
+    field public static final java.lang.String COMEDY = "Comedy";
+    field public static final java.lang.String DRAMA = "Drama";
+    field public static final java.lang.String EDUCATION = "Education";
+    field public static final java.lang.String FAMILY_KIDS = "Family/Kids";
+    field public static final java.lang.String GAMING = "Gaming";
+    field public static final java.lang.String MOVIES = "Movies";
+    field public static final java.lang.String NEWS = "News";
+    field public static final java.lang.String SHOPPING = "Shopping";
+    field public static final java.lang.String SPORTS = "Sports";
+    field public static final java.lang.String TRAVEL = "Travel";
+  }
+
+  public final class TvInputInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getId();
+    method public android.content.Intent getIntentForSettingsActivity();
+    method public android.content.Intent getIntentForSetupActivity();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getServiceName();
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String EXTRA_SERVICE_NAME = "serviceName";
+  }
+
+  public final class TvInputManager {
+    method public void createSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler);
+    method public boolean getAvailability(java.lang.String);
+    method public java.util.List<android.media.tv.TvInputInfo> getTvInputList();
+    method public void registerListener(java.lang.String, android.media.tv.TvInputManager.TvInputListener, android.os.Handler);
+    method public void unregisterListener(java.lang.String, android.media.tv.TvInputManager.TvInputListener);
+  }
+
+  public static final class TvInputManager.Session {
+    method public void release();
+    method public void setVolume(float);
+    method public void tune(android.net.Uri);
+  }
+
+  public static abstract class TvInputManager.SessionCallback {
+    ctor public TvInputManager.SessionCallback();
+    method public void onSessionCreated(android.media.tv.TvInputManager.Session);
+    method public void onSessionReleased(android.media.tv.TvInputManager.Session);
+  }
+
+  public static abstract class TvInputManager.TvInputListener {
+    ctor public TvInputManager.TvInputListener();
+    method public void onAvailabilityChanged(java.lang.String, boolean);
+  }
+
+  public abstract class TvInputService extends android.app.Service {
+    ctor public TvInputService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.media.tv.TvInputService.TvInputSessionImpl onCreateSession();
+    method public final void setAvailable(boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
+  }
+
+  public abstract class TvInputService.TvInputSessionImpl implements android.view.KeyEvent.Callback {
+    ctor public TvInputService.TvInputSessionImpl();
+    method public android.view.View onCreateOverlayView();
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
+    method public abstract void onRelease();
+    method public abstract boolean onSetSurface(android.view.Surface);
+    method public abstract void onSetVolume(float);
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public abstract boolean onTune(android.net.Uri);
+    method public void setOverlayViewEnabled(boolean);
+  }
+
+  public class TvView extends android.view.SurfaceView {
+    ctor public TvView(android.content.Context);
+    ctor public TvView(android.content.Context, android.util.AttributeSet);
+    ctor public TvView(android.content.Context, android.util.AttributeSet, int);
+    method public void bindTvInput(java.lang.String, android.media.tv.TvInputManager.SessionCallback);
+    method public boolean dispatchUnhandledInputEvent(android.view.InputEvent);
+    method public boolean onUnhandledInputEvent(android.view.InputEvent);
+    method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
+    method public void unbindTvInput();
+  }
+
+  public static abstract interface TvView.OnUnhandledInputEventListener {
+    method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
+  }
+
+}
+
 package android.mtp {
 
   public final class MtpConstants {
@@ -24945,81 +25115,6 @@
     field public static final java.lang.String TYPE = "type";
   }
 
-  public final class TvContract {
-    method public static final android.net.Uri buildChannelUri(long);
-    method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName);
-    method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName, boolean);
-    method public static final android.net.Uri buildProgramUri(long);
-    method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri);
-    method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
-    field public static final java.lang.String AUTHORITY = "com.android.tv";
-  }
-
-  public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
-    field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
-  }
-
-  public static final class TvContract.Channels implements android.provider.TvContract.BaseTvColumns {
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_DATA = "data";
-    field public static final java.lang.String COLUMN_DESCRIPTION = "description";
-    field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
-    field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
-    field public static final java.lang.String COLUMN_LOCKED = "locked";
-    field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
-    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
-    field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
-    field public static final java.lang.String COLUMN_SERVICE_NAME = "service_name";
-    field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
-    field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
-    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.channels";
-    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.channels";
-    field public static final android.net.Uri CONTENT_URI;
-    field public static final int SERVICE_TYPE_OTHER = 0; // 0x0
-    field public static final int SERVICE_TYPE_RADIO = 2; // 0x2
-    field public static final int SERVICE_TYPE_TV = 1; // 0x1
-    field public static final int TYPE_1SEG = 263168; // 0x40400
-    field public static final int TYPE_ATSC_C = 197120; // 0x30200
-    field public static final int TYPE_ATSC_M_H = 197120; // 0x30200
-    field public static final int TYPE_ATSC_T = 196608; // 0x30000
-    field public static final int TYPE_CMMB = 327936; // 0x50100
-    field public static final int TYPE_DTMB = 327680; // 0x50000
-    field public static final int TYPE_DVB_C = 131584; // 0x20200
-    field public static final int TYPE_DVB_C2 = 131585; // 0x20201
-    field public static final int TYPE_DVB_H = 131840; // 0x20300
-    field public static final int TYPE_DVB_S = 131328; // 0x20100
-    field public static final int TYPE_DVB_S2 = 131329; // 0x20101
-    field public static final int TYPE_DVB_SH = 132096; // 0x20400
-    field public static final int TYPE_DVB_T = 131072; // 0x20000
-    field public static final int TYPE_DVB_T2 = 131073; // 0x20001
-    field public static final int TYPE_ISDB_C = 262912; // 0x40300
-    field public static final int TYPE_ISDB_S = 262656; // 0x40200
-    field public static final int TYPE_ISDB_T = 262144; // 0x40000
-    field public static final int TYPE_ISDB_TB = 262400; // 0x40100
-    field public static final int TYPE_OTHER = 0; // 0x0
-    field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
-    field public static final int TYPE_S_DMB = 393472; // 0x60100
-    field public static final int TYPE_T_DMB = 393216; // 0x60000
-  }
-
-  public static final class TvContract.Programs implements android.provider.TvContract.BaseTvColumns {
-    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
-    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
-    field public static final java.lang.String COLUMN_DATA = "data";
-    field public static final java.lang.String COLUMN_DESCRIPTION = "description";
-    field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
-    field public static final java.lang.String COLUMN_GENRE = "genre";
-    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_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_TITLE = "title";
-    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
-    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.programs";
-    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.programs";
-    field public static final android.net.Uri CONTENT_URI;
-  }
-
   public class UserDictionary {
     ctor public UserDictionary();
     field public static final java.lang.String AUTHORITY = "user_dictionary";
@@ -30593,85 +30688,6 @@
 
 }
 
-package android.tv {
-
-  public final class TvInputInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.content.ComponentName getComponent();
-    method public java.lang.String getId();
-    method public java.lang.String getPackageName();
-    method public java.lang.String getServiceName();
-    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
-    method public void writeToParcel(android.os.Parcel, int);
-  }
-
-  public final class TvInputManager {
-    method public void createSession(java.lang.String, android.tv.TvInputManager.SessionCallback, android.os.Handler);
-    method public boolean getAvailability(java.lang.String);
-    method public java.util.List<android.tv.TvInputInfo> getTvInputList();
-    method public void registerListener(java.lang.String, android.tv.TvInputManager.TvInputListener, android.os.Handler);
-    method public void unregisterListener(java.lang.String, android.tv.TvInputManager.TvInputListener);
-  }
-
-  public static final class TvInputManager.Session {
-    method public void release();
-    method public void setVolume(float);
-    method public void tune(android.net.Uri);
-  }
-
-  public static abstract class TvInputManager.SessionCallback {
-    ctor public TvInputManager.SessionCallback();
-    method public void onSessionCreated(android.tv.TvInputManager.Session);
-    method public void onSessionReleased(android.tv.TvInputManager.Session);
-  }
-
-  public static abstract class TvInputManager.TvInputListener {
-    ctor public TvInputManager.TvInputListener();
-    method public void onAvailabilityChanged(java.lang.String, boolean);
-  }
-
-  public abstract class TvInputService extends android.app.Service {
-    ctor public TvInputService();
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.tv.TvInputService.TvInputSessionImpl onCreateSession();
-    method public final void setAvailable(boolean);
-    field public static final java.lang.String SERVICE_INTERFACE = "android.tv.TvInputService";
-  }
-
-  public abstract class TvInputService.TvInputSessionImpl implements android.view.KeyEvent.Callback {
-    ctor public TvInputService.TvInputSessionImpl();
-    method public android.view.View onCreateOverlayView();
-    method public boolean onGenericMotionEvent(android.view.MotionEvent);
-    method public boolean onKeyDown(int, android.view.KeyEvent);
-    method public boolean onKeyLongPress(int, android.view.KeyEvent);
-    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
-    method public boolean onKeyUp(int, android.view.KeyEvent);
-    method public abstract void onRelease();
-    method public abstract boolean onSetSurface(android.view.Surface);
-    method public abstract void onSetVolume(float);
-    method public boolean onTouchEvent(android.view.MotionEvent);
-    method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public abstract boolean onTune(android.net.Uri);
-    method public void setOverlayViewEnabled(boolean);
-  }
-
-  public class TvView extends android.view.SurfaceView {
-    ctor public TvView(android.content.Context);
-    ctor public TvView(android.content.Context, android.util.AttributeSet);
-    ctor public TvView(android.content.Context, android.util.AttributeSet, int);
-    method public void bindTvInput(java.lang.String, android.tv.TvInputManager.SessionCallback);
-    method public boolean dispatchUnhandledInputEvent(android.view.InputEvent);
-    method public boolean onUnhandledInputEvent(android.view.InputEvent);
-    method public void setOnUnhandledInputEventListener(android.tv.TvView.OnUnhandledInputEventListener);
-    method public void unbindTvInput();
-  }
-
-  public static abstract interface TvView.OnUnhandledInputEventListener {
-    method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
-  }
-
-}
-
 package android.util {
 
   public class AndroidException extends java.lang.Exception {
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java
index 2673031..4503726 100644
--- a/cmds/bu/src/com/android/commands/bu/Backup.java
+++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -20,6 +20,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.system.OsConstants;
 import android.util.Log;
 
 import java.io.IOException;
@@ -50,13 +51,11 @@
             return;
         }
 
-        int socketFd = Integer.parseInt(nextArg());
-
         String arg = nextArg();
         if (arg.equals("backup")) {
-            doFullBackup(socketFd);
+            doFullBackup(OsConstants.STDOUT_FILENO);
         } else if (arg.equals("restore")) {
-            doFullRestore(socketFd);
+            doFullRestore(OsConstants.STDIN_FILENO);
         } else {
             Log.e(TAG, "Invalid operation '" + arg + "'");
         }
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index b7c2c22..47047b8 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -39,6 +39,7 @@
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IUserManager;
 import android.os.Process;
@@ -57,7 +58,6 @@
 import java.util.Comparator;
 import java.util.List;
 import java.util.WeakHashMap;
-
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
@@ -823,6 +823,7 @@
         byte[] tag = null;
         String originatingUriString = null;
         String referrer = null;
+        String abi = null;
 
         while ((opt=nextOption()) != null) {
             if (opt.equals("-l")) {
@@ -893,12 +894,34 @@
                     System.err.println("Error: must supply argument for --referrer");
                     return;
                 }
+            } else if (opt.equals("--abi")) {
+                abi = nextOptionData();
+                if (abi == null) {
+                    System.err.println("Error: must supply argument for --abi");
+                    return;
+                }
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 return;
             }
         }
 
+        if (abi != null) {
+            final String[] supportedAbis = Build.SUPPORTED_ABIS;
+            boolean matched = false;
+            for (String supportedAbi : supportedAbis) {
+                if (supportedAbi.equals(abi)) {
+                    matched = true;
+                    break;
+                }
+            }
+
+            if (!matched) {
+                System.err.println("Error: abi " + abi + " not supported on this device.");
+                return;
+            }
+        }
+
         final ContainerEncryptionParams encryptionParams;
         if (algo != null || iv != null || key != null || macAlgo != null || macKey != null
                 || tag != null) {
@@ -976,8 +999,9 @@
             VerificationParams verificationParams = new VerificationParams(verificationURI,
                     originatingURI, referrerURI, VerificationParams.NO_UID, null);
 
-            mPm.installPackageWithVerificationAndEncryptionEtc(apkURI, null, obs, installFlags,
-                    installerPackageName, verificationParams, encryptionParams);
+            mPm.installPackageWithVerificationEncryptionAndAbiOverrideEtc(apkURI, null,
+                    obs, installFlags, installerPackageName, verificationParams,
+                    encryptionParams, abi);
 
             synchronized (obs) {
                 while (!obs.finished) {
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 5e4ddd0..b739387 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -129,8 +129,8 @@
     protected static final String KEY_SCALE_TYPE = "shared_element:scaleType";
     protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
 
-    // The background fade in/out duration. 150ms is pretty quick, but not abrupt.
-    public static final int FADE_BACKGROUND_DURATION_MS = 150;
+    // The background fade in/out duration. TODO: Enable tuning this.
+    public static final int FADE_BACKGROUND_DURATION_MS = 300;
 
     protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
 
@@ -195,6 +195,11 @@
      */
     public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
 
+    /**
+     * Send the shared element positions.
+     */
+    public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108;
+
     final private Window mWindow;
     final protected ArrayList<String> mAllSharedElementNames;
     final protected ArrayList<View> mSharedElements = new ArrayList<View>();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4f335bb..e03224c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -75,6 +75,8 @@
 import android.media.AudioManager;
 import android.media.MediaRouter;
 import android.media.session.MediaSessionManager;
+import android.media.tv.ITvInputManager;
+import android.media.tv.TvInputManager;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.EthernetManager;
@@ -119,8 +121,6 @@
 import android.service.fingerprint.FingerprintManagerReceiver;
 import android.service.fingerprint.FingerprintService;
 import android.telephony.TelephonyManager;
-import android.tv.ITvInputManager;
-import android.tv.TvInputManager;
 import android.content.ClipboardManager;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index a8617b8..4b052e7 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -29,6 +29,7 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewGroupOverlay;
 import android.view.ViewTreeObserver;
 import android.widget.ImageView;
@@ -72,8 +73,24 @@
                 }
             };
             mHandler.sendEmptyMessageDelayed(MSG_CANCEL, MAX_WAIT_MS);
+            send(MSG_SEND_SHARED_ELEMENT_DESTINATION, null);
+        }
+    }
+
+    private void sendSharedElementDestination() {
+        ViewGroup decor = getDecor();
+        if (!decor.isLayoutRequested()) {
             Bundle state = captureSharedElementState();
             mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
+        } else {
+            getDecor().getViewTreeObserver()
+                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                            return true;
+                        }
+                    });
         }
     }
 
@@ -105,6 +122,9 @@
             case MSG_CANCEL:
                 cancel();
                 break;
+            case MSG_SEND_SHARED_ELEMENT_DESTINATION:
+                sendSharedElementDestination();
+                break;
         }
     }
 
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index a71d649..ba1638ff 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -294,7 +294,7 @@
     }
 
     private void finishIfNecessary() {
-        if (mIsReturning && mExitNotified && (mSharedElements.isEmpty()
+        if (mIsReturning && mExitNotified && mActivity != null && (mSharedElements.isEmpty()
                 || mSharedElements.get(0).getVisibility() == View.INVISIBLE)) {
             mActivity.finish();
             mActivity.overridePendingTransition(0, 0);
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index f332c9d..85e970c 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -43,7 +43,7 @@
  * {@link Request} subclass describing the type of operation to perform -- currently the
  * possible requests are {@link ConfirmationRequest} and {@link CommandRequest}.
  *
- * <p>Once a request is submitted, the voice system will process it and evetually deliver
+ * <p>Once a request is submitted, the voice system will process it and eventually deliver
  * the result to the request object.  The application can cancel a pending request at any
  * time.
  *
@@ -51,7 +51,7 @@
  * if an activity is being restarted with retained state, it will retain the current
  * VoiceInteractor and any outstanding requests.  Because of this, you should always use
  * {@link Request#getActivity() Request.getActivity} to get back to the activity of a
- * request, rather than holding on to the actvitity instance yourself, either explicitly
+ * request, rather than holding on to the activity instance yourself, either explicitly
  * or implicitly through a non-static inner class.
  */
 public class VoiceInteractor {
@@ -236,7 +236,7 @@
          * Reports that the current interaction can not be complete with voice, so the
          * application will need to switch to a traditional input UI.  Applications should
          * only use this when they need to completely bail out of the voice interaction
-         * and switch to a traditional UI.  When the resonsponse comes back, the voice
+         * and switch to a traditional UI.  When the response comes back, the voice
          * system has handled the request and is ready to switch; at that point the application
          * can start a new non-voice activity.  Be sure when starting the new activity
          * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b3b1d47..afe2981 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -104,6 +104,17 @@
         = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
 
     /**
+     * A broadcast intent with this action can be sent to ManagedProvisionning to specify that the
+     * user has already consented to the creation of the managed profile.
+     * The intent must contain the extras
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} and
+     * {@link #EXTRA_PROVISIONING_TOKEN}
+     * @hide
+     */
+    public static final String ACTION_PROVISIONING_USER_HAS_CONSENTED
+        = "android.app.action.USER_HAS_CONSENTED";
+
+    /**
      * A String extra holding the name of the package of the mobile device management application
      * that starts the managed provisioning flow. This package will be set as the profile owner.
      * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}.
@@ -112,6 +123,13 @@
         = "deviceAdminPackageName";
 
     /**
+     * An int extra used to identify the consent of the user to create the managed profile.
+     * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
+     */
+    public static final String EXTRA_PROVISIONING_TOKEN
+        = "android.app.extra.token";
+
+    /**
      * A String extra holding the default name of the profile that is created during managed profile
      * provisioning.
      * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index da5cb10..46f082e 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -22,7 +22,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 
-import com.android.internal.backup.BackupConstants;
 import com.android.internal.backup.IBackupTransport;
 
 /**
@@ -32,6 +31,13 @@
  * @hide
  */
 public class BackupTransport {
+    public static final int TRANSPORT_OK = 0;
+    public static final int TRANSPORT_ERROR = 1;
+    public static final int TRANSPORT_NOT_INITIALIZED = 2;
+    public static final int TRANSPORT_PACKAGE_REJECTED = 3;
+    public static final int AGENT_ERROR = 4;
+    public static final int AGENT_UNKNOWN = 5;
+
     IBackupTransport mBinderImpl = new TransportImpl();
     /** @hide */
     public IBinder getBinder() {
@@ -99,10 +105,50 @@
     }
 
     // ------------------------------------------------------------------------------------
+    // Device-level operations common to both key/value and full-data storage
+
+    /**
+     * Initialize the server side storage for this device, erasing all stored data.
+     * The transport may send the request immediately, or may buffer it.  After
+     * this is called, {@link #finishBackup} will be called to ensure the request
+     * is sent and received successfully.
+     *
+     * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far) or
+     *   {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure).
+     */
+    public int initializeDevice() {
+        return BackupTransport.TRANSPORT_ERROR;
+    }
+
+    /**
+     * Erase the given application's data from the backup destination.  This clears
+     * out the given package's data from the current backup set, making it as though
+     * the app had never yet been backed up.  After this is called, {@link finishBackup}
+     * must be called to ensure that the operation is recorded successfully.
+     *
+     * @return the same error codes as {@link #performBackup}.
+     */
+    public int clearBackupData(PackageInfo packageInfo) {
+        return BackupTransport.TRANSPORT_ERROR;
+    }
+
+    /**
+     * Finish sending application data to the backup destination.  This must be
+     * called after {@link #performBackup}, {@link #performFullBackup}, or {@link clearBackupData}
+     * to ensure that all data is sent and the operation properly finalized.  Only when this
+     * method returns true can a backup be assumed to have succeeded.
+     *
+     * @return the same error codes as {@link #performBackup} or {@link #performFullBackup}.
+     */
+    public int finishBackup() {
+        return BackupTransport.TRANSPORT_ERROR;
+    }
+
+    // ------------------------------------------------------------------------------------
     // Key/value incremental backup support interfaces
 
     /**
-     * Verify that this is a suitable time for a backup pass.  This should return zero
+     * Verify that this is a suitable time for a key/value backup pass.  This should return zero
      * if a backup is reasonable right now, some positive value otherwise.  This method
      * will be called outside of the {@link #performBackup}/{@link #finishBackup} pair.
      *
@@ -117,19 +163,6 @@
     }
 
     /**
-     * Initialize the server side storage for this device, erasing all stored data.
-     * The transport may send the request immediately, or may buffer it.  After
-     * this is called, {@link #finishBackup} will be called to ensure the request
-     * is sent and received successfully.
-     *
-     * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or
-     *   {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure).
-     */
-    public int initializeDevice() {
-        return BackupConstants.TRANSPORT_ERROR;
-    }
-
-    /**
      * Send one application's key/value data update to the backup destination.  The
      * transport may send the data immediately, or may buffer it.  After this is called,
      * {@link #finishBackup} will be called to ensure the data is sent and recorded successfully.
@@ -143,37 +176,13 @@
      *   must be erased prior to the storage of the data provided here.  The purpose of this
      *   is to provide a guarantee that no stale data exists in the restore set when the
      *   device begins providing incremental backups.
-     * @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far),
-     *  {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or
-     *  {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
+     * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far),
+     *  {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), or
+     *  {@link BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
      *  become lost due to inactivity purge or some other reason and needs re-initializing)
      */
     public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) {
-        return BackupConstants.TRANSPORT_ERROR;
-    }
-
-    /**
-     * Erase the give application's data from the backup destination.  This clears
-     * out the given package's data from the current backup set, making it as though
-     * the app had never yet been backed up.  After this is called, {@link finishBackup}
-     * must be called to ensure that the operation is recorded successfully.
-     *
-     * @return the same error codes as {@link #performBackup}.
-     */
-    public int clearBackupData(PackageInfo packageInfo) {
-        return BackupConstants.TRANSPORT_ERROR;
-    }
-
-    /**
-     * Finish sending application data to the backup destination.  This must be
-     * called after {@link #performBackup} or {@link clearBackupData} to ensure that
-     * all data is sent.  Only when this method returns true can a backup be assumed
-     * to have succeeded.
-     *
-     * @return the same error codes as {@link #performBackup}.
-     */
-    public int finishBackup() {
-        return BackupConstants.TRANSPORT_ERROR;
+        return BackupTransport.TRANSPORT_ERROR;
     }
 
     // ------------------------------------------------------------------------------------
@@ -210,12 +219,12 @@
      *   or {@link #getCurrentRestoreSet}.
      * @param packages List of applications to restore (if data is available).
      *   Application data will be restored in the order given.
-     * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
-     *   {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR}
+     * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far, call
+     *   {@link #nextRestorePackage}) or {@link BackupTransport#TRANSPORT_ERROR}
      *   (an error occurred, the restore should be aborted and rescheduled).
      */
     public int startRestore(long token, PackageInfo[] packages) {
-        return BackupConstants.TRANSPORT_ERROR;
+        return BackupTransport.TRANSPORT_ERROR;
     }
 
     /**
@@ -235,7 +244,7 @@
      * @return the same error codes as {@link #startRestore}.
      */
     public int getRestoreData(ParcelFileDescriptor outFd) {
-        return BackupConstants.TRANSPORT_ERROR;
+        return BackupTransport.TRANSPORT_ERROR;
     }
 
     /**
@@ -247,6 +256,78 @@
                 "Transport finishRestore() not implemented");
     }
 
+    // ------------------------------------------------------------------------------------
+    // Full backup interfaces
+
+    /**
+     * Verify that this is a suitable time for a full-data backup pass.  This should return zero
+     * if a backup is reasonable right now, some positive value otherwise.  This method
+     * will be called outside of the {@link #performFullBackup}/{@link #finishBackup} pair.
+     *
+     * <p>If this is not a suitable time for a backup, the transport should return a
+     * backoff delay, in milliseconds, after which the Backup Manager should try again.
+     *
+     * @return Zero if this is a suitable time for a backup pass, or a positive time delay
+     *   in milliseconds to suggest deferring the backup pass for a while.
+     *
+     * @see #requestBackupTime()
+     */
+    public long requestFullBackupTime() {
+        return 0;
+    }
+
+    /**
+     * Begin the process of sending an application's full-data archive to the backend.
+     * The description of the package whose data will be delivered is provided, as well as
+     * the socket file descriptor on which the transport will receive the data itself.
+     *
+     * <p>If the package is not eligible for backup, the transport should return
+     * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED}.  In this case the system will
+     * simply proceed with the next candidate if any, or finish the full backup operation
+     * if all apps have been processed.
+     *
+     * <p>After the transport returns {@link BackupTransport#TRANSPORT_OK} from this
+     * method, the OS will proceed to call {@link #sendBackupData()} one or more times
+     * to deliver the application's data as a streamed tarball.  The transport should not
+     * read() from the socket except as instructed to via the {@link #sendBackupData(int)}
+     * method.
+     *
+     * <p>After all data has been delivered to the transport, the system will call
+     * {@link #finishBackup()}.  At this point the transport should commit the data to
+     * its datastore, if appropriate, and close the socket that had been provided in
+     * {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}.
+     *
+     * @param targetPackage The package whose data is to follow.
+     * @param socket The socket file descriptor through which the data will be provided.
+     *    If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still
+     *    close this file descriptor now; otherwise it should be cached for use during
+     *    succeeding calls to {@link #sendBackupData(int)}, and closed in response to
+     *    {@link #finishBackup()}.
+     * @return TRANSPORT_PACKAGE_REJECTED to indicate that the stated application is not
+     *    to be backed up; TRANSPORT_OK to indicate that the OS may proceed with delivering
+     *    backup data; TRANSPORT_ERROR to indicate a fatal error condition that precludes
+     *    performing a backup at this time.
+     */
+    public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) {
+        return BackupTransport.TRANSPORT_PACKAGE_REJECTED;
+    }
+
+    /**
+     * Tells the transport to read {@code numBytes} bytes of data from the socket file
+     * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}
+     * call, and deliver those bytes to the datastore.
+     *
+     * @param numBytes The number of bytes of tarball data available to be read from the
+     *    socket.
+     * @return TRANSPORT_OK on successful processing of the data; TRANSPORT_ERROR to
+     *    indicate a fatal error situation.  If an error is returned, the system will
+     *    call finishBackup() and stop attempting backups until after a backoff and retry
+     *    interval.
+     */
+    public int sendBackupData(int numBytes) {
+        return BackupTransport.TRANSPORT_ERROR;
+    }
+
     /**
      * Bridge between the actual IBackupTransport implementation and the stable API.  If the
      * binder interface needs to change, we use this layer to translate so that we can
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c69e669..a040efb 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2751,11 +2751,11 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.tv.TvInputManager} for interacting with TV inputs on the
-     * device.
+     * {@link android.media.tv.TvInputManager} for interacting with TV inputs
+     * on the device.
      *
      * @see #getSystemService
-     * @see android.tv.TvInputManager
+     * @see android.media.tv.TvInputManager
      */
     public static final String TV_INPUT_SERVICE = "tv_input";
 
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 44a6a5d..70668e1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -433,6 +433,13 @@
             in VerificationParams verificationParams,
             in ContainerEncryptionParams encryptionParams);
 
+    void installPackageWithVerificationEncryptionAndAbiOverrideEtc(in Uri packageURI,
+            in IPackageInstallObserver observer, in IPackageInstallObserver2 observer2,
+            int flags, in String installerPackageName,
+            in VerificationParams verificationParams,
+            in ContainerEncryptionParams encryptionParams,
+	    in String packageAbiOverride);
+
     int installExistingPackageAsUser(String packageName, int userId);
 
     void verifyPendingInstall(int id, int verificationCode);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3737638..ed3f9aa 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -702,12 +702,17 @@
      * Context.obtainStyledAttributes} with
      * an array containing the resource ID of interest to create the TypedArray.</p>
      *
+     * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
+     * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
+     * or {@link #getDrawable(int, Theme)} passing the desired theme.</p>
+     *
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
      * @return Drawable An object that can be used to draw this resource.
      * @throws NotFoundException Throws NotFoundException if the given ID does
      *         not exist.
+     * @see #getDrawable(int, Theme)
      */
     public Drawable getDrawable(int id) throws NotFoundException {
         return getDrawable(id, null);
@@ -715,7 +720,9 @@
 
     /**
      * Return a drawable object associated with a particular resource ID and
-     * styled for the specified theme.
+     * styled for the specified theme. Various types of objects will be
+     * returned depending on the underlying resource -- for example, a solid
+     * color, PNG image, scalable image, etc.
      *
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
@@ -755,6 +762,11 @@
      * image, scalable image, etc. The Drawable API hides these implementation
      * details.
      *
+     * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
+     * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
+     * or {@link #getDrawableForDensity(int, int, Theme)} passing the desired
+     * theme.</p>
+     *
      * @param id The desired resource identifier, as generated by the aapt tool.
      *            This integer encodes the package, type, and resource entry.
      *            The value 0 is an invalid identifier.
@@ -2340,12 +2352,12 @@
             if (file.endsWith(".xml")) {
                 final XmlResourceParser rp = loadXmlResourceParser(
                         file, id, value.assetCookie, "drawable");
-                dr = Drawable.createFromXmlThemed(this, rp, theme);
+                dr = Drawable.createFromXml(this, rp, theme);
                 rp.close();
             } else {
                 final InputStream is = mAssets.openNonAsset(
                         value.assetCookie, file, AssetManager.ACCESS_STREAMING);
-                dr = Drawable.createFromResourceStreamThemed(this, value, is, file, null, theme);
+                dr = Drawable.createFromResourceStream(this, value, is, file, null);
                 is.close();
             }
         } catch (Exception e) {
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index a71a74d..723eda1 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -194,6 +194,8 @@
         DEVICE_RECORDER,  // ADDR_RECORDER_3
         DEVICE_TUNER,  // ADDR_TUNER_4
         DEVICE_PLAYBACK,  // ADDR_PLAYBACK_3
+        DEVICE_RESERVED,
+        DEVICE_RESERVED,
         DEVICE_TV,  // ADDR_SPECIFIC_USE
     };
 
@@ -210,6 +212,8 @@
         "Recorder_3",
         "Tuner_4",
         "Playback_3",
+        "Reserved_1",
+        "Reserved_2",
         "Secondary_TV",
     };
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2f2aba3..a48a388 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -40,6 +40,7 @@
 import android.util.Log;
 
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Protocol;
 
 import java.net.InetAddress;
@@ -807,11 +808,34 @@
      * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
      */
     public int startUsingNetworkFeature(int networkType, String feature) {
-        try {
-            return mService.startUsingNetworkFeature(networkType, feature,
-                    new Binder());
-        } catch (RemoteException e) {
-            return -1;
+        NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
+        if (netCap == null) {
+            Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " +
+                    feature);
+            return PhoneConstants.APN_REQUEST_FAILED;
+        }
+
+        NetworkRequest request = null;
+        synchronized (sLegacyRequests) {
+            LegacyRequest l = sLegacyRequests.get(netCap);
+            if (l != null) {
+                Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest);
+                renewRequestLocked(l);
+                if (l.currentNetwork != null) {
+                    return PhoneConstants.APN_ALREADY_ACTIVE;
+                } else {
+                    return PhoneConstants.APN_REQUEST_STARTED;
+                }
+            }
+
+            request = requestNetworkForFeatureLocked(netCap);
+        }
+        if (request != null) {
+            Log.d(TAG, "starting startUsingNeworkFeature for request " + request);
+            return PhoneConstants.APN_REQUEST_STARTED;
+        } else {
+            Log.d(TAG, " request Failed");
+            return PhoneConstants.APN_REQUEST_FAILED;
         }
     }
 
@@ -831,11 +855,172 @@
      * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
      */
     public int stopUsingNetworkFeature(int networkType, String feature) {
-        try {
-            return mService.stopUsingNetworkFeature(networkType, feature);
-        } catch (RemoteException e) {
+        NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
+        if (netCap == null) {
+            Log.d(TAG, "Can't satisfy stopUsingNetworkFeature for " + networkType + ", " +
+                    feature);
             return -1;
         }
+
+        NetworkRequest request = removeRequestForFeature(netCap);
+        if (request != null) {
+            Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature);
+            releaseNetworkRequest(request);
+        }
+        return 1;
+    }
+
+    private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) {
+        if (networkType == TYPE_MOBILE) {
+            int cap = -1;
+            if ("enableMMS".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_MMS;
+            } else if ("enableSUPL".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_SUPL;
+            } else if ("enableDUN".equals(feature) || "enableDUNAlways".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_DUN;
+            } else if ("enableHIPRI".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_INTERNET;
+            } else if ("enableFOTA".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_FOTA;
+            } else if ("enableIMS".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_IMS;
+            } else if ("enableCBS".equals(feature)) {
+                cap = NetworkCapabilities.NET_CAPABILITY_CBS;
+            } else {
+                return null;
+            }
+            NetworkCapabilities netCap = new NetworkCapabilities();
+            netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+            netCap.addNetworkCapability(cap);
+            return netCap;
+        } else if (networkType == TYPE_WIFI) {
+            if ("p2p".equals(feature)) {
+                NetworkCapabilities netCap = new NetworkCapabilities();
+                netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+                netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
+                return netCap;
+            }
+        }
+        return null;
+    }
+
+    private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
+        if (netCap == null) return TYPE_NONE;
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
+            return TYPE_MOBILE_CBS;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+            return TYPE_MOBILE_IMS;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
+            return TYPE_MOBILE_FOTA;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
+            return TYPE_MOBILE_DUN;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+            return TYPE_MOBILE_SUPL;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+            return TYPE_MOBILE_MMS;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+            return TYPE_MOBILE_HIPRI;
+        }
+        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) {
+            return TYPE_WIFI_P2P;
+        }
+        return TYPE_NONE;
+    }
+
+    private static class LegacyRequest {
+        NetworkCapabilities networkCapabilities;
+        NetworkRequest networkRequest;
+        int expireSequenceNumber;
+        Network currentNetwork;
+        int delay = -1;
+        NetworkCallbackListener networkCallbackListener = new NetworkCallbackListener() {
+            @Override
+            public void onAvailable(NetworkRequest request, Network network) {
+                currentNetwork = network;
+                Log.d(TAG, "startUsingNetworkFeature got Network:" + network);
+                network.bindProcessForHostResolution();
+            }
+            @Override
+            public void onLost(NetworkRequest request, Network network) {
+                if (network.equals(currentNetwork)) {
+                    currentNetwork = null;
+                    network.unbindProcessForHostResolution();
+                }
+                Log.d(TAG, "startUsingNetworkFeature lost Network:" + network);
+            }
+        };
+    }
+
+    private HashMap<NetworkCapabilities, LegacyRequest> sLegacyRequests =
+            new HashMap<NetworkCapabilities, LegacyRequest>();
+
+    private NetworkRequest findRequestForFeature(NetworkCapabilities netCap) {
+        synchronized (sLegacyRequests) {
+            LegacyRequest l = sLegacyRequests.get(netCap);
+            if (l != null) return l.networkRequest;
+        }
+        return null;
+    }
+
+    private void renewRequestLocked(LegacyRequest l) {
+        l.expireSequenceNumber++;
+        Log.d(TAG, "renewing request to seqNum " + l.expireSequenceNumber);
+        sendExpireMsgForFeature(l.networkCapabilities, l.expireSequenceNumber, l.delay);
+    }
+
+    private void expireRequest(NetworkCapabilities netCap, int sequenceNum) {
+        int ourSeqNum = -1;
+        synchronized (sLegacyRequests) {
+            LegacyRequest l = sLegacyRequests.get(netCap);
+            if (l == null) return;
+            ourSeqNum = l.expireSequenceNumber;
+            if (l.expireSequenceNumber == sequenceNum) {
+                releaseNetworkRequest(l.networkRequest);
+                sLegacyRequests.remove(netCap);
+            }
+        }
+        Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum);
+    }
+
+    private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) {
+        int delay = -1;
+        int type = legacyTypeForNetworkCapabilities(netCap);
+        try {
+            delay = mService.getRestoreDefaultNetworkDelay(type);
+        } catch (RemoteException e) {}
+        LegacyRequest l = new LegacyRequest();
+        l.networkCapabilities = netCap;
+        l.delay = delay;
+        l.expireSequenceNumber = 0;
+        l.networkRequest = sendRequestForNetwork(netCap, l.networkCallbackListener, 0,
+                REQUEST, type);
+        if (l.networkRequest == null) return null;
+        sLegacyRequests.put(netCap, l);
+        sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay);
+        return l.networkRequest;
+    }
+
+    private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) {
+        if (delay >= 0) {
+            Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay);
+            Message msg = sCallbackHandler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap);
+            sCallbackHandler.sendMessageDelayed(msg, delay);
+        }
+    }
+
+    private NetworkRequest removeRequestForFeature(NetworkCapabilities netCap) {
+        synchronized (sLegacyRequests) {
+            LegacyRequest l = sLegacyRequests.remove(netCap);
+            if (l == null) return null;
+            return l.networkRequest;
+        }
     }
 
     /**
@@ -1782,8 +1967,10 @@
     public static final int CALLBACK_RELEASED           = BASE + 8;
     /** @hide */
     public static final int CALLBACK_EXIT               = BASE + 9;
+    /** @hide obj = NetworkCapabilities, arg1 = seq number */
+    private static final int EXPIRE_LEGACY_REQUEST      = BASE + 10;
 
-    private static class CallbackHandler extends Handler {
+    private class CallbackHandler extends Handler {
         private final HashMap<NetworkRequest, NetworkCallbackListener>mCallbackMap;
         private final AtomicInteger mRefCount;
         private static final String TAG = "ConnectivityManager.CallbackHandler";
@@ -1903,6 +2090,10 @@
                     getLooper().quit();
                     break;
                 }
+                case EXPIRE_LEGACY_REQUEST: {
+                    expireRequest((NetworkCapabilities)message.obj, message.arg1);
+                    break;
+                }
             }
         }
 
@@ -1954,8 +2145,9 @@
     private final static int LISTEN  = 1;
     private final static int REQUEST = 2;
 
-    private NetworkRequest somethingForNetwork(NetworkCapabilities need,
-            NetworkCallbackListener networkCallbackListener, int timeoutSec, int action) {
+    private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
+            NetworkCallbackListener networkCallbackListener, int timeoutSec, int action,
+            int legacyType) {
         NetworkRequest networkRequest = null;
         if (networkCallbackListener == null) {
             throw new IllegalArgumentException("null NetworkCallbackListener");
@@ -1968,7 +2160,7 @@
                         new Binder());
             } else {
                 networkRequest = mService.requestNetwork(need, new Messenger(sCallbackHandler),
-                        timeoutSec, new Binder());
+                        timeoutSec, new Binder(), legacyType);
             }
             if (networkRequest != null) {
                 synchronized(sNetworkCallbackListener) {
@@ -1998,7 +2190,7 @@
      */
     public NetworkRequest requestNetwork(NetworkCapabilities need,
             NetworkCallbackListener networkCallbackListener) {
-        return somethingForNetwork(need, networkCallbackListener, 0, REQUEST);
+        return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, TYPE_NONE);
     }
 
     /**
@@ -2021,7 +2213,8 @@
      */
     public NetworkRequest requestNetwork(NetworkCapabilities need,
             NetworkCallbackListener networkCallbackListener, int timeoutSec) {
-        return somethingForNetwork(need, networkCallbackListener, timeoutSec, REQUEST);
+        return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST,
+                TYPE_NONE);
     }
 
     /**
@@ -2099,7 +2292,7 @@
      */
     public NetworkRequest listenForNetwork(NetworkCapabilities need,
             NetworkCallbackListener networkCallbackListener) {
-        return somethingForNetwork(need, networkCallbackListener, 0, LISTEN);
+        return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, TYPE_NONE);
     }
 
     /**
diff --git a/core/java/android/net/ConnectivityServiceProtocol.java b/core/java/android/net/ConnectivityServiceProtocol.java
deleted file mode 100644
index 74096b4..0000000
--- a/core/java/android/net/ConnectivityServiceProtocol.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static com.android.internal.util.Protocol.BASE_CONNECTIVITY_SERVICE;
-
-/**
- * Describes the Internal protocols used to communicate with ConnectivityService.
- * @hide
- */
-public class ConnectivityServiceProtocol {
-
-    private static final int BASE = BASE_CONNECTIVITY_SERVICE;
-
-    private ConnectivityServiceProtocol() {}
-
-    /**
-     * This is a contract between ConnectivityService and various bearers.
-     * A NetworkFactory is an abstract entity that creates NetworkAgent objects.
-     * The bearers register with ConnectivityService using
-     * ConnectivityManager.registerNetworkFactory, where they pass in a Messenger
-     * to be used to deliver the following Messages.
-     */
-    public static class NetworkFactoryProtocol {
-        private NetworkFactoryProtocol() {}
-        /**
-         * Pass a network request to the bearer.  If the bearer believes it can
-         * satisfy the request it should connect to the network and create a
-         * NetworkAgent.  Once the NetworkAgent is fully functional it will
-         * register itself with ConnectivityService using registerNetworkAgent.
-         * If the bearer cannot immediately satisfy the request (no network,
-         * user disabled the radio, lower-scored network) it should remember
-         * any NetworkRequests it may be able to satisfy in the future.  It may
-         * disregard any that it will never be able to service, for example
-         * those requiring a different bearer.
-         * msg.obj = NetworkRequest
-         * msg.arg1 = score - the score of the any network currently satisfying this
-         *            request.  If this bearer knows in advance it cannot
-         *            exceed this score it should not try to connect, holding the request
-         *            for the future.
-         *            Note that subsequent events may give a different (lower
-         *            or higher) score for this request, transmitted to each
-         *            NetworkFactory through additional CMD_REQUEST_NETWORK msgs
-         *            with the same NetworkRequest but an updated score.
-         *            Also, network conditions may change for this bearer
-         *            allowing for a better score in the future.
-         */
-        public static final int CMD_REQUEST_NETWORK = BASE;
-
-        /**
-         * Cancel a network request
-         * msg.obj = NetworkRequest
-         */
-        public static final int CMD_CANCEL_REQUEST = BASE + 1;
-    }
-}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index baec36a..5f1ff3e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -158,7 +158,7 @@
             in NetworkCapabilities nc, int score);
 
     NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
-            in Messenger messenger, int timeoutSec, in IBinder binder);
+            in Messenger messenger, int timeoutSec, in IBinder binder, int legacy);
 
     NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
             in PendingIntent operation);
@@ -170,4 +170,6 @@
             in PendingIntent operation);
 
     void releaseNetworkRequest(in NetworkRequest networkRequest);
+
+    int getRestoreDefaultNetworkDelay(int networkType);
 }
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 1c18ba5..7e8b1f1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -24,85 +24,39 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
-import android.util.SparseArray;
 
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
+import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * A Utility class for handling NetworkRequests.
- *
- * Created by bearer-specific code to handle tracking requests, scores,
- * network data and handle communicating with ConnectivityService.  Two
- * abstract methods: connect and disconnect are used to act on the
- * underlying bearer code.  Connect is called when we have a NetworkRequest
- * and our score is better than the current handling network's score, while
- * disconnect is used when ConnectivityService requests a disconnect.
+ * A Utility class for handling for communicating between bearer-specific
+ * code and ConnectivityService.
  *
  * A bearer may have more than one NetworkAgent if it can simultaneously
  * support separate networks (IMS / Internet / MMS Apns on cellular, or
- * perhaps connections with different SSID or P2P for Wi-Fi).  The bearer
- * code should pass its NetworkAgents the NetworkRequests each NetworkAgent
- * can handle, demultiplexing for different network types.  The bearer code
- * can also filter out requests it can never handle.
+ * perhaps connections with different SSID or P2P for Wi-Fi).
  *
- * Each NetworkAgent needs to be given a score and NetworkCapabilities for
- * their potential network.  While disconnected, the NetworkAgent will check
- * each time its score changes or a NetworkRequest changes to see if
- * the NetworkAgent can provide a higher scored network for a NetworkRequest
- * that the NetworkAgent's NetworkCapabilties can satisfy.  This condition will
- * trigger a connect request via connect().  After connection, connection data
- * should be given to the NetworkAgent by the bearer, including LinkProperties
- * NetworkCapabilties and NetworkInfo.  After that the NetworkAgent will register
- * with ConnectivityService and forward the data on.
  * @hide
  */
 public abstract class NetworkAgent extends Handler {
-    private final SparseArray<NetworkRequestAndScore> mNetworkRequests = new SparseArray<>();
-    private boolean mConnectionRequested = false;
-
-    private AsyncChannel mAsyncChannel;
+    private volatile AsyncChannel mAsyncChannel;
     private final String LOG_TAG;
     private static final boolean DBG = true;
     private static final boolean VDBG = true;
-    // TODO - this class shouldn't cache data or it runs the risk of getting out of sync
-    // Make the API require each of these when any is updated so we have the data we need,
-    // without caching.
-    private LinkProperties mLinkProperties;
-    private NetworkInfo mNetworkInfo;
-    private NetworkCapabilities mNetworkCapabilities;
-    private int mNetworkScore;
-    private boolean mRegistered = false;
     private final Context mContext;
-    private AtomicBoolean mHasRequests = new AtomicBoolean(false);
-
-    // TODO - add a name member for logging purposes.
-
-    protected final Object mLockObj = new Object();
-
+    private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
 
     private static final int BASE = Protocol.BASE_NETWORK_AGENT;
 
     /**
-     * Sent by self to queue up a new/modified request.
-     * obj = NetworkRequestAndScore
-     */
-    private static final int CMD_ADD_REQUEST = BASE + 1;
-
-    /**
-     * Sent by self to queue up the removal of a request.
-     * obj = NetworkRequest
-     */
-    private static final int CMD_REMOVE_REQUEST = BASE + 2;
-
-    /**
      * Sent by ConnectivityService to the NetworkAgent to inform it of
      * suspected connectivity problems on its network.  The NetworkAgent
      * should take steps to verify and correct connectivity.
      */
-    public static final int CMD_SUSPECT_BAD = BASE + 3;
+    public static final int CMD_SUSPECT_BAD = BASE;
 
     /**
      * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to
@@ -110,84 +64,63 @@
      * Sent when the NetworkInfo changes, mainly due to change of state.
      * obj = NetworkInfo
      */
-    public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 4;
+    public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1;
 
     /**
      * Sent by the NetworkAgent to ConnectivityService to pass the current
      * NetworkCapabilties.
      * obj = NetworkCapabilities
      */
-    public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 5;
+    public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2;
 
     /**
      * Sent by the NetworkAgent to ConnectivityService to pass the current
      * NetworkProperties.
      * obj = NetworkProperties
      */
-    public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 6;
+    public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3;
 
     /**
      * Sent by the NetworkAgent to ConnectivityService to pass the current
      * network score.
-     * arg1 = network score int
+     * obj = network score Integer
      */
-    public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 7;
+    public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
 
-    public NetworkAgent(Looper looper, Context context, String logTag) {
+    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
+            NetworkCapabilities nc, LinkProperties lp, int score) {
         super(looper);
         LOG_TAG = logTag;
         mContext = context;
-    }
-
-    /**
-     * When conditions are right, register with ConnectivityService.
-     * Connditions include having a well defined network and a request
-     * that justifies it.  The NetworkAgent will remain registered until
-     * disconnected.
-     * TODO - this should have all data passed in rather than caching
-     */
-    private void registerSelf() {
-        synchronized(mLockObj) {
-            if (!mRegistered && mConnectionRequested &&
-                    mNetworkInfo != null && mNetworkInfo.isConnected() &&
-                    mNetworkCapabilities != null &&
-                    mLinkProperties != null &&
-                    mNetworkScore != 0) {
-                if (DBG) log("Registering NetworkAgent");
-                mRegistered = true;
-                ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
-                        Context.CONNECTIVITY_SERVICE);
-                cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(mNetworkInfo),
-                        new LinkProperties(mLinkProperties),
-                        new NetworkCapabilities(mNetworkCapabilities), mNetworkScore);
-            } else if (DBG && !mRegistered) {
-                String err = "Not registering due to ";
-                if (mConnectionRequested == false) err += "no Connect requested ";
-                if (mNetworkInfo == null) err += "null NetworkInfo ";
-                if (mNetworkInfo != null && mNetworkInfo.isConnected() == false) {
-                    err += "NetworkInfo disconnected ";
-                }
-                if (mLinkProperties == null) err += "null LinkProperties ";
-                if (mNetworkCapabilities == null) err += "null NetworkCapabilities ";
-                if (mNetworkScore == 0) err += "null NetworkScore";
-                log(err);
-            }
+        if (ni == null || nc == null || lp == null) {
+            throw new IllegalArgumentException();
         }
+
+        if (DBG) log("Registering NetworkAgent");
+        ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
+                new LinkProperties(lp), new NetworkCapabilities(nc), score);
     }
 
     @Override
     public void handleMessage(Message msg) {
         switch (msg.what) {
             case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
-                synchronized (mLockObj) {
-                    if (mAsyncChannel != null) {
-                        log("Received new connection while already connected!");
-                    } else {
-                        if (DBG) log("NetworkAgent fully connected");
-                        mAsyncChannel = new AsyncChannel();
-                        mAsyncChannel.connected(null, this, msg.replyTo);
-                        mAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
-                                AsyncChannel.STATUS_SUCCESSFUL);
+                if (mAsyncChannel != null) {
+                    log("Received new connection while already connected!");
+                } else {
+                    if (DBG) log("NetworkAgent fully connected");
+                    AsyncChannel ac = new AsyncChannel();
+                    ac.connected(null, this, msg.replyTo);
+                    ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+                            AsyncChannel.STATUS_SUCCESSFUL);
+                    synchronized (mPreConnectedQueue) {
+                        mAsyncChannel = ac;
+                        for (Message m : mPreConnectedQueue) {
+                            ac.sendMessage(m);
+                        }
+                        mPreConnectedQueue.clear();
                     }
                 }
                 break;
@@ -199,213 +132,69 @@
             }
             case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
                 if (DBG) log("NetworkAgent channel lost");
-                disconnect();
-                clear();
+                // let the client know CS is done with us.
+                unwanted();
+                synchronized (mPreConnectedQueue) {
+                    mAsyncChannel = null;
+                }
                 break;
             }
             case CMD_SUSPECT_BAD: {
                 log("Unhandled Message " + msg);
                 break;
             }
-            case CMD_ADD_REQUEST: {
-                handleAddRequest(msg);
-                break;
-            }
-            case CMD_REMOVE_REQUEST: {
-                handleRemoveRequest(msg);
-                break;
-            }
         }
     }
 
-    private void clear() {
-        synchronized(mLockObj) {
-            mNetworkRequests.clear();
-            mHasRequests.set(false);
-            mConnectionRequested = false;
-            mAsyncChannel = null;
-            mRegistered = false;
-        }
-    }
-
-    private static class NetworkRequestAndScore {
-        NetworkRequest req;
-        int score;
-
-        NetworkRequestAndScore(NetworkRequest networkRequest, int score) {
-            req = networkRequest;
-            this.score = score;
-        }
-    }
-
-    private void handleAddRequest(Message msg) {
-        NetworkRequestAndScore n = (NetworkRequestAndScore)msg.obj;
-        // replaces old request, updating score
-        mNetworkRequests.put(n.req.requestId, n);
-        mHasRequests.set(true);
-        evalScores();
-    }
-
-    private void handleRemoveRequest(Message msg) {
-        NetworkRequest networkRequest = (NetworkRequest)msg.obj;
-
-        if (mNetworkRequests.get(networkRequest.requestId) != null) {
-            mNetworkRequests.remove(networkRequest.requestId);
-            if (mNetworkRequests.size() == 0) mHasRequests.set(false);
-            evalScores();
-        }
-    }
-
-    /**
-     * Called to go through our list of requests and see if we're
-     * good enough to try connecting, or if we have gotten worse and
-     * need to disconnect.
-     *
-     * Once we are registered, does nothing: we disconnect when requested via
-     * CMD_CHANNEL_DISCONNECTED, generated by either a loss of connection
-     * between modules (bearer or ConnectivityService dies) or more commonly
-     * when the NetworkInfo reports to ConnectivityService it is disconnected.
-     */
-    private void evalScores() {
-        synchronized(mLockObj) {
-            if (mRegistered) {
-                if (VDBG) log("evalScores - already connected - size=" + mNetworkRequests.size());
-                // already trying
-                return;
-            }
-            if (VDBG) log("evalScores!");
-            for (int i=0; i < mNetworkRequests.size(); i++) {
-                int score = mNetworkRequests.valueAt(i).score;
-                if (VDBG) log(" checking request Min " + score + " vs my score " + mNetworkScore);
-                if (score < mNetworkScore) {
-                    // have a request that has a lower scored network servicing it
-                    // (or no network) than we could provide, so let's connect!
-                    mConnectionRequested = true;
-                    connect();
-                    return;
-                }
-            }
-            // Our score is not high enough to satisfy any current request.
-            // This can happen if our score goes down after a connection is
-            // requested but before we actually connect. In this case, disconnect
-            // rather than continue trying - there's no point connecting if we know
-            // we'll just be torn down as soon as we do.
-            if (mConnectionRequested) {
-                mConnectionRequested = false;
-                disconnect();
+    private void queueOrSendMessage(int what, Object obj) {
+        synchronized (mPreConnectedQueue) {
+            if (mAsyncChannel != null) {
+                mAsyncChannel.sendMessage(what, obj);
+            } else {
+                Message msg = Message.obtain();
+                msg.what = what;
+                msg.obj = obj;
+                mPreConnectedQueue.add(msg);
             }
         }
     }
 
-    public void addNetworkRequest(NetworkRequest networkRequest, int score) {
-        if (DBG) log("adding NetworkRequest " + networkRequest + " with score " + score);
-        sendMessage(obtainMessage(CMD_ADD_REQUEST,
-                new NetworkRequestAndScore(networkRequest, score)));
-    }
-
-    public void removeNetworkRequest(NetworkRequest networkRequest) {
-        if (DBG) log("removing NetworkRequest " + networkRequest);
-        sendMessage(obtainMessage(CMD_REMOVE_REQUEST, networkRequest));
-    }
-
     /**
      * Called by the bearer code when it has new LinkProperties data.
-     * If we're a registered NetworkAgent, this new data will get forwarded on,
-     * otherwise we store a copy in anticipation of registering.  This call
-     * may also prompt registration if it causes the NetworkAgent to meet
-     * the conditions (fully configured, connected, satisfys a request and
-     * has sufficient score).
      */
     public void sendLinkProperties(LinkProperties linkProperties) {
-        linkProperties = new LinkProperties(linkProperties);
-        synchronized(mLockObj) {
-            mLinkProperties = linkProperties;
-            if (mAsyncChannel != null) {
-                mAsyncChannel.sendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, linkProperties);
-            } else {
-                registerSelf();
-            }
-        }
+        queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
     }
 
     /**
      * Called by the bearer code when it has new NetworkInfo data.
-     * If we're a registered NetworkAgent, this new data will get forwarded on,
-     * otherwise we store a copy in anticipation of registering.  This call
-     * may also prompt registration if it causes the NetworkAgent to meet
-     * the conditions (fully configured, connected, satisfys a request and
-     * has sufficient score).
      */
     public void sendNetworkInfo(NetworkInfo networkInfo) {
-        networkInfo = new NetworkInfo(networkInfo);
-        synchronized(mLockObj) {
-            mNetworkInfo = networkInfo;
-            if (mAsyncChannel != null) {
-                mAsyncChannel.sendMessage(EVENT_NETWORK_INFO_CHANGED, networkInfo);
-            } else {
-                registerSelf();
-            }
-        }
+        queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
     }
 
     /**
      * Called by the bearer code when it has new NetworkCapabilities data.
-     * If we're a registered NetworkAgent, this new data will get forwarded on,
-     * otherwise we store a copy in anticipation of registering.  This call
-     * may also prompt registration if it causes the NetworkAgent to meet
-     * the conditions (fully configured, connected, satisfys a request and
-     * has sufficient score).
-     * Note that if these capabilities make the network non-useful,
-     * ConnectivityServce will tear this network down.
      */
     public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
-        networkCapabilities = new NetworkCapabilities(networkCapabilities);
-        synchronized(mLockObj) {
-            mNetworkCapabilities = networkCapabilities;
-            if (mAsyncChannel != null) {
-                mAsyncChannel.sendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, networkCapabilities);
-            } else {
-                registerSelf();
-            }
-        }
-    }
-
-    public NetworkCapabilities getNetworkCapabilities() {
-        synchronized(mLockObj) {
-            return new NetworkCapabilities(mNetworkCapabilities);
-        }
+        queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
+                new NetworkCapabilities(networkCapabilities));
     }
 
     /**
      * Called by the bearer code when it has a new score for this network.
-     * If we're a registered NetworkAgent, this new data will get forwarded on,
-     * otherwise we store a copy.
      */
-    public synchronized void sendNetworkScore(int score) {
-        synchronized(mLockObj) {
-            mNetworkScore = score;
-            evalScores();
-            if (mAsyncChannel != null) {
-                mAsyncChannel.sendMessage(EVENT_NETWORK_SCORE_CHANGED, mNetworkScore);
-            } else {
-                registerSelf();
-            }
-        }
+    public void sendNetworkScore(int score) {
+        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
     }
 
-    public boolean hasRequests() {
-        return mHasRequests.get();
-    }
-
-    public boolean isConnectionRequested() {
-        synchronized(mLockObj) {
-            return mConnectionRequested;
-        }
-    }
-
-
-    abstract protected void connect();
-    abstract protected void disconnect();
+    /**
+     * Called when ConnectivityService has indicated they no longer want this network.
+     * The parent factory should (previously) have received indication of the change
+     * as well, either canceling NetworkRequests or altering their score such that this
+     * network won't be immediately requested again.
+     */
+    abstract protected void unwanted();
 
     protected void log(String s) {
         Log.d(LOG_TAG, "NetworkAgent: " + s);
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
new file mode 100644
index 0000000..a20e8e7
--- /dev/null
+++ b/core/java/android/net/NetworkFactory.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+/**
+ * A NetworkFactory is an entity that creates NetworkAgent objects.
+ * The bearers register with ConnectivityService using {@link #register} and
+ * their factory will start receiving scored NetworkRequests.  NetworkRequests
+ * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
+ * overridden function.  All of these can be dynamic - changing NetworkCapabilities
+ * or score forces re-evaluation of all current requests.
+ *
+ * If any requests pass the filter some overrideable functions will be called.
+ * If the bearer only cares about very simple start/stopNetwork callbacks, those
+ * functions can be overridden.  If the bearer needs more interaction, it can
+ * override addNetworkRequest and removeNetworkRequest which will give it each
+ * request that passes their current filters.
+ * @hide
+ **/
+public class NetworkFactory extends Handler {
+    private static final boolean DBG = true;
+
+    private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
+    /**
+     * Pass a network request to the bearer.  If the bearer believes it can
+     * satisfy the request it should connect to the network and create a
+     * NetworkAgent.  Once the NetworkAgent is fully functional it will
+     * register itself with ConnectivityService using registerNetworkAgent.
+     * If the bearer cannot immediately satisfy the request (no network,
+     * user disabled the radio, lower-scored network) it should remember
+     * any NetworkRequests it may be able to satisfy in the future.  It may
+     * disregard any that it will never be able to service, for example
+     * those requiring a different bearer.
+     * msg.obj = NetworkRequest
+     * msg.arg1 = score - the score of the any network currently satisfying this
+     *            request.  If this bearer knows in advance it cannot
+     *            exceed this score it should not try to connect, holding the request
+     *            for the future.
+     *            Note that subsequent events may give a different (lower
+     *            or higher) score for this request, transmitted to each
+     *            NetworkFactory through additional CMD_REQUEST_NETWORK msgs
+     *            with the same NetworkRequest but an updated score.
+     *            Also, network conditions may change for this bearer
+     *            allowing for a better score in the future.
+     */
+    public static final int CMD_REQUEST_NETWORK = BASE;
+
+    /**
+     * Cancel a network request
+     * msg.obj = NetworkRequest
+     */
+    public static final int CMD_CANCEL_REQUEST = BASE + 1;
+
+    /**
+     * Internally used to set our best-guess score.
+     * msg.arg1 = new score
+     */
+    private static final int CMD_SET_SCORE = BASE + 2;
+
+    /**
+     * Internally used to set our current filter for coarse bandwidth changes with
+     * technology changes.
+     * msg.obj = new filter
+     */
+    private static final int CMD_SET_FILTER = BASE + 3;
+
+    private final Context mContext;
+    private final String LOG_TAG;
+
+    private final SparseArray<NetworkRequestInfo> mNetworkRequests =
+            new SparseArray<NetworkRequestInfo>();
+
+    private int mScore;
+    private NetworkCapabilities mCapabilityFilter;
+
+    private int mRefCount = 0;
+    private Messenger mMessenger = null;
+
+    public NetworkFactory(Looper looper, Context context, String logTag,
+            NetworkCapabilities filter) {
+        super(looper);
+        LOG_TAG = logTag;
+        mContext = context;
+        mCapabilityFilter = filter;
+    }
+
+    public void register() {
+        if (DBG) log("Registering NetworkFactory");
+        if (mMessenger == null) {
+            mMessenger = new Messenger(this);
+            ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
+        }
+    }
+
+    public void unregister() {
+        if (DBG) log("Unregistering NetworkFactory");
+        if (mMessenger != null) {
+            ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
+            mMessenger = null;
+        }
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        switch (msg.what) {
+            case CMD_REQUEST_NETWORK: {
+                handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
+                break;
+            }
+            case CMD_CANCEL_REQUEST: {
+                handleRemoveRequest((NetworkRequest) msg.obj);
+                break;
+            }
+            case CMD_SET_SCORE: {
+                handleSetScore(msg.arg1);
+                break;
+            }
+            case CMD_SET_FILTER: {
+                handleSetFilter((NetworkCapabilities) msg.obj);
+                break;
+            }
+        }
+    }
+
+    private class NetworkRequestInfo {
+        public final NetworkRequest request;
+        public int score;
+        public boolean requested; // do we have a request outstanding, limited by score
+
+        public NetworkRequestInfo(NetworkRequest request, int score) {
+            this.request = request;
+            this.score = score;
+            this.requested = false;
+        }
+    }
+
+    private void handleAddRequest(NetworkRequest request, int score) {
+        NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
+        if (n == null) {
+            n = new NetworkRequestInfo(request, score);
+            mNetworkRequests.put(n.request.requestId, n);
+        } else {
+            n.score = score;
+        }
+        if (DBG) log("got request " + request + " with score " + score);
+        if (DBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);
+
+        evalRequest(n);
+    }
+
+    private void handleRemoveRequest(NetworkRequest request) {
+        NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
+        if (n != null && n.requested) {
+            mNetworkRequests.remove(request.requestId);
+            releaseNetworkFor(n.request);
+        }
+    }
+
+    private void handleSetScore(int score) {
+        mScore = score;
+        evalRequests();
+    }
+
+    private void handleSetFilter(NetworkCapabilities netCap) {
+        mCapabilityFilter = netCap;
+        evalRequests();
+    }
+
+    /**
+     * Overridable function to provide complex filtering.
+     * Called for every request every time a new NetworkRequest is seen
+     * and whenever the filterScore or filterNetworkCapabilities change.
+     *
+     * acceptRequest can be overriden to provide complex filter behavior
+     * for the incoming requests
+     *
+     * For output, this class will call {@link #needNetworkFor} and
+     * {@link #releaseNetworkFor} for every request that passes the filters.
+     * If you don't need to see every request, you can leave the base
+     * implementations of those two functions and instead override
+     * {@link #startNetwork} and {@link #stopNetwork}.
+     *
+     * If you want to see every score fluctuation on every request, set
+     * your score filter to a very high number and watch {@link #needNetworkFor}.
+     *
+     * @return {@code true} to accept the request.
+     */
+    public boolean acceptRequest(NetworkRequest request, int score) {
+        return true;
+    }
+
+    private void evalRequest(NetworkRequestInfo n) {
+        if (n.requested == false && n.score < mScore &&
+                n.request.networkCapabilities.satisfiedByNetworkCapabilities(
+                mCapabilityFilter) && acceptRequest(n.request, n.score)) {
+            needNetworkFor(n.request, n.score);
+            n.requested = true;
+        } else if (n.requested == true &&
+                (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
+                mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
+            releaseNetworkFor(n.request);
+            n.requested = false;
+        }
+    }
+
+    private void evalRequests() {
+        for (int i = 0; i < mNetworkRequests.size(); i++) {
+            NetworkRequestInfo n = mNetworkRequests.valueAt(i);
+
+            evalRequest(n);
+        }
+    }
+
+    // override to do simple mode (request independent)
+    protected void startNetwork() { }
+    protected void stopNetwork() { }
+
+    // override to do fancier stuff
+    protected void needNetworkFor(NetworkRequest networkRequest, int score) {
+        if (++mRefCount == 1) startNetwork();
+    }
+
+    protected void releaseNetworkFor(NetworkRequest networkRequest) {
+        if (--mRefCount == 0) stopNetwork();
+    }
+
+
+    public void addNetworkRequest(NetworkRequest networkRequest, int score) {
+        sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
+                new NetworkRequestInfo(networkRequest, score)));
+    }
+
+    public void removeNetworkRequest(NetworkRequest networkRequest) {
+        sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
+    }
+
+    public void setScoreFilter(int score) {
+        sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
+    }
+
+    public void setCapabilityFilter(NetworkCapabilities netCap) {
+        sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, s);
+    }
+}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 9e656ee..d279412 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -188,6 +188,15 @@
     }
 
     /**
+     * @hide
+     */
+    public void setType(int type) {
+        synchronized (this) {
+            mNetworkType = type;
+        }
+    }
+
+    /**
      * Return a network-type-specific integer describing the subtype
      * of the network.
      * @return the network subtype
@@ -198,7 +207,10 @@
         }
     }
 
-    void setSubtype(int subtype, String subtypeName) {
+    /**
+     * @hide
+     */
+    public void setSubtype(int subtype, String subtypeName) {
         synchronized (this) {
             mSubtype = subtype;
             mSubtypeName = subtypeName;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 480cb057..47377e9 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -47,19 +47,19 @@
     public final int requestId;
 
     /**
-     * Set for legacy requests and the default.
+     * Set for legacy requests and the default.  Set to TYPE_NONE for none.
      * Causes CONNECTIVITY_ACTION broadcasts to be sent.
      * @hide
      */
-    public final boolean needsBroadcasts;
+    public final int legacyType;
 
     /**
      * @hide
      */
-    public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) {
+    public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
         requestId = rId;
         networkCapabilities = nc;
-        this.needsBroadcasts = needsBroadcasts;
+        this.legacyType = legacyType;
     }
 
     /**
@@ -68,7 +68,7 @@
     public NetworkRequest(NetworkRequest that) {
         networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
         requestId = that.requestId;
-        needsBroadcasts = that.needsBroadcasts;
+        this.legacyType = that.legacyType;
     }
 
     // implement the Parcelable interface
@@ -77,16 +77,16 @@
     }
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(networkCapabilities, flags);
-        dest.writeInt(needsBroadcasts ? 1 : 0);
+        dest.writeInt(legacyType);
         dest.writeInt(requestId);
     }
     public static final Creator<NetworkRequest> CREATOR =
         new Creator<NetworkRequest>() {
             public NetworkRequest createFromParcel(Parcel in) {
                 NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
-                boolean needsBroadcasts = (in.readInt() == 1);
+                int legacyType = in.readInt();
                 int requestId = in.readInt();
-                NetworkRequest result = new NetworkRequest(nc, needsBroadcasts, requestId);
+                NetworkRequest result = new NetworkRequest(nc, legacyType, requestId);
                 return result;
             }
             public NetworkRequest[] newArray(int size) {
@@ -95,14 +95,14 @@
         };
 
     public String toString() {
-        return "NetworkRequest [ id=" + requestId + ", needsBroadcasts=" + needsBroadcasts +
+        return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType +
                 ", " + networkCapabilities.toString() + " ]";
     }
 
     public boolean equals(Object obj) {
         if (obj instanceof NetworkRequest == false) return false;
         NetworkRequest that = (NetworkRequest)obj;
-        return (that.needsBroadcasts == this.needsBroadcasts &&
+        return (that.legacyType == this.legacyType &&
                 that.requestId == this.requestId &&
                 ((that.networkCapabilities == null && this.networkCapabilities == null) ||
                  (that.networkCapabilities != null &&
@@ -110,7 +110,7 @@
     }
 
     public int hashCode() {
-        return requestId + (needsBroadcasts ? 1013 : 2026) +
+        return requestId + (legacyType * 1013) +
                 (networkCapabilities.hashCode() * 1051);
     }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index bc57b33..e627d49 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -931,6 +931,14 @@
         }
     }
 
+    /**
+     * Don't allow any more batching in to the current history event.  This
+     * is called when printing partial histories, so to ensure that the next
+     * history event will go in to a new batch after what was printed in the
+     * last partial history.
+     */
+    public abstract void commitCurrentHistoryBatchLocked();
+
     public abstract int getHistoryTotalSize();
 
     public abstract int getHistoryUsedSize();
@@ -3366,6 +3374,7 @@
             }
         }
         if (histStart >= 0) {
+            commitCurrentHistoryBatchLocked();
             pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
         }
     }
diff --git a/core/java/android/tv/TvInputInfo.java b/core/java/android/tv/TvInputInfo.java
deleted file mode 100644
index 217e4b7..0000000
--- a/core/java/android/tv/TvInputInfo.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.tv;
-
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to specify meta information of a TV input.
- */
-public final class TvInputInfo implements Parcelable {
-    private final ResolveInfo mService;
-    private final String mId;
-
-    /**
-     * Constructor.
-     *
-     * @param service The ResolveInfo returned from the package manager about this TV input service.
-     * @hide
-     */
-    public TvInputInfo(ResolveInfo service) {
-        mService = service;
-        ServiceInfo si = service.serviceInfo;
-        mId = generateInputIdForComponentName(new ComponentName(si.packageName, si.name));
-    }
-
-    /**
-     * Returns a unique ID for this TV input. The ID is generated from the package and class name
-     * implementing the TV input service.
-     */
-    public String getId() {
-        return mId;
-    }
-
-    /**
-     * Returns the .apk package that implements this TV input service.
-     */
-    public String getPackageName() {
-        return mService.serviceInfo.packageName;
-    }
-
-    /**
-     * Returns the class name of the service component that implements this TV input service.
-     */
-    public String getServiceName() {
-        return mService.serviceInfo.name;
-    }
-
-    /**
-     * Returns the component of the service that implements this TV input.
-     */
-    public ComponentName getComponent() {
-        return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
-    }
-
-    /**
-     * Loads the user-displayed label for this TV input service.
-     *
-     * @param pm Supplies a PackageManager used to load the TV input's resources.
-     * @return a CharSequence containing the TV input's label. If the TV input does not have
-     *         a label, its name is returned.
-     */
-    public CharSequence loadLabel(PackageManager pm) {
-        return mService.loadLabel(pm);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public int hashCode() {
-        return mId.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == this) {
-            return true;
-        }
-
-        if (!(o instanceof TvInputInfo)) {
-            return false;
-        }
-
-        TvInputInfo obj = (TvInputInfo) o;
-        return mId.equals(obj.mId)
-                && mService.serviceInfo.packageName.equals(obj.mService.serviceInfo.packageName)
-                && mService.serviceInfo.name.equals(obj.mService.serviceInfo.name);
-    }
-
-    @Override
-    public String toString() {
-        return "TvInputInfo{id=" + mId
-                + ", pkg=" + mService.serviceInfo.packageName
-                + ", service=" + mService.serviceInfo.name + "}";
-    }
-
-    /**
-     * Used to package this object into a {@link Parcel}.
-     *
-     * @param dest The {@link Parcel} to be written.
-     * @param flags The flags used for parceling.
-     */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mId);
-        mService.writeToParcel(dest, flags);
-    }
-
-    /**
-     * Used to generate an input id from a ComponentName.
-     *
-     * @param name the component name for generating an input id.
-     * @return the generated input id for the given {@code name}.
-     * @hide
-     */
-    public static final String generateInputIdForComponentName(ComponentName name) {
-        return name.flattenToShortString();
-    }
-
-    /**
-     * Used to make this class parcelable.
-     *
-     * @hide
-     */
-    public static final Parcelable.Creator<TvInputInfo> CREATOR =
-            new Parcelable.Creator<TvInputInfo>() {
-        @Override
-        public TvInputInfo createFromParcel(Parcel in) {
-            return new TvInputInfo(in);
-        }
-
-        @Override
-        public TvInputInfo[] newArray(int size) {
-            return new TvInputInfo[size];
-        }
-    };
-
-    private TvInputInfo(Parcel in) {
-        mId = in.readString();
-        mService = ResolveInfo.CREATOR.createFromParcel(in);
-    }
-}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 424d860..5056097 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -75,22 +75,10 @@
     // Constructors
     ///////////////////////////////////////////////////////////////////////////
 
-    /**
-     * Creates a canvas to render directly on screen.
-     */
-    GLES20Canvas(boolean translucent) {
-        this(false, translucent);
-    }
-    
-    protected GLES20Canvas(boolean record, boolean translucent) {
-        mOpaque = !translucent;
-
-        if (record) {
-            mRenderer = nCreateDisplayListRenderer();
-        } else {
-            mRenderer = nCreateRenderer();
-        }
-
+    // TODO: Merge with GLES20RecordingCanvas
+    protected GLES20Canvas() {
+        mOpaque = false;
+        mRenderer = nCreateDisplayListRenderer();
         setupFinalizer();
     }
 
@@ -102,7 +90,6 @@
         }
     }
 
-    private static native long nCreateRenderer();
     private static native long nCreateDisplayListRenderer();
     private static native void nResetDisplayListRenderer(long renderer);
     private static native void nDestroyRenderer(long renderer);
@@ -131,36 +118,6 @@
     private static native void nSetProperty(String name, String value);
 
     ///////////////////////////////////////////////////////////////////////////
-    // Hardware layers
-    ///////////////////////////////////////////////////////////////////////////
-
-    @Override
-    void pushLayerUpdate(HardwareLayer layer) {
-        nPushLayerUpdate(mRenderer, layer.getLayer());
-    }
-
-    @Override
-    void cancelLayerUpdate(HardwareLayer layer) {
-        nCancelLayerUpdate(mRenderer, layer.getLayer());
-    }
-
-    @Override
-    void flushLayerUpdates() {
-        nFlushLayerUpdates(mRenderer);
-    }
-
-    @Override
-    void clearLayerUpdates() {
-        nClearLayerUpdates(mRenderer);
-    }
-
-    static native boolean nCopyLayer(long layerId, long bitmap);
-    private static native void nClearLayerUpdates(long renderer);
-    private static native void nFlushLayerUpdates(long renderer);
-    private static native void nPushLayerUpdate(long renderer, long layer);
-    private static native void nCancelLayerUpdate(long renderer, long layer);
-
-    ///////////////////////////////////////////////////////////////////////////
     // Canvas management
     ///////////////////////////////////////////////////////////////////////////
 
@@ -234,20 +191,6 @@
 
     private static native void nFinish(long renderer);
 
-    /**
-     * Returns the size of the stencil buffer required by the underlying
-     * implementation.
-     * 
-     * @return The minimum number of bits the stencil buffer must. Always >= 0.
-     * 
-     * @hide
-     */
-    public static int getStencilSize() {
-        return nGetStencilSize();
-    }
-
-    private static native int nGetStencilSize();
-
     ///////////////////////////////////////////////////////////////////////////
     // Functor
     ///////////////////////////////////////////////////////////////////////////
@@ -284,49 +227,6 @@
      */
     static final int FLUSH_CACHES_FULL = 2;
 
-    /**
-     * Flush caches to reclaim as much memory as possible. The amount of memory
-     * to reclaim is indicate by the level parameter.
-     * 
-     * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
-     * {@link #FLUSH_CACHES_FULL}.
-     * 
-     * @param level Hint about the amount of memory to reclaim
-     */
-    static void flushCaches(int level) {
-        nFlushCaches(level);
-    }
-
-    private static native void nFlushCaches(int level);
-
-    /**
-     * Release all resources associated with the underlying caches. This should
-     * only be called after a full flushCaches().
-     * 
-     * @hide
-     */
-    static void terminateCaches() {
-        nTerminateCaches();
-    }
-
-    private static native void nTerminateCaches();
-
-    static boolean initCaches() {
-        return nInitCaches();
-    }
-
-    private static native boolean nInitCaches();
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Atlas
-    ///////////////////////////////////////////////////////////////////////////
-
-    static void initAtlas(GraphicBuffer buffer, long[] map) {
-        nInitAtlas(buffer, map, map.length);
-    }
-
-    private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count);
-
     ///////////////////////////////////////////////////////////////////////////
     // Display list
     ///////////////////////////////////////////////////////////////////////////
@@ -899,12 +799,6 @@
     private static native void nDrawPath(long renderer, long path, long paint);
     private static native void nDrawRects(long renderer, long region, long paint);
 
-    void drawRects(float[] rects, int count, Paint paint) {
-        nDrawRects(mRenderer, rects, count, paint.mNativePaint);
-    }
-
-    private static native void nDrawRects(long renderer, float[] rects, int count, long paint);
-
     @Override
     public void drawPicture(Picture picture) {
         if (picture.createdFromStream) {
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index a94ec3a..b2961e5 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -36,7 +36,7 @@
     RenderNode mNode;
 
     private GLES20RecordingCanvas() {
-        super(true, true);
+        super();
     }
 
     static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
deleted file mode 100644
index f1163e2..0000000
--- a/core/java/android/view/GLRenderer.java
+++ /dev/null
@@ -1,1521 +0,0 @@
-/*
- * 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.
- */
-
-package android.view;
-
-import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_BAD_NATIVE_WINDOW;
-import static javax.microedition.khronos.egl.EGL10.EGL_BLUE_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_CONFIG_CAVEAT;
-import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_DEPTH_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_DRAW;
-import static javax.microedition.khronos.egl.EGL10.EGL_GREEN_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_HEIGHT;
-import static javax.microedition.khronos.egl.EGL10.EGL_NONE;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_CONTEXT;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_SURFACE;
-import static javax.microedition.khronos.egl.EGL10.EGL_RED_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_RENDERABLE_TYPE;
-import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLES;
-import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLE_BUFFERS;
-import static javax.microedition.khronos.egl.EGL10.EGL_STENCIL_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_SUCCESS;
-import static javax.microedition.khronos.egl.EGL10.EGL_SURFACE_TYPE;
-import static javax.microedition.khronos.egl.EGL10.EGL_WIDTH;
-import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT;
-
-import android.content.ComponentCallbacks2;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
-import android.opengl.EGL14;
-import android.opengl.GLUtils;
-import android.opengl.ManagedEGLContext;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.Trace;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.Surface.OutOfResourcesException;
-
-import com.google.android.gles_jni.EGLImpl;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
-
-/**
- * Hardware renderer using OpenGL
- *
- * @hide
- */
-public class GLRenderer extends HardwareRenderer {
-    static final int SURFACE_STATE_ERROR = 0;
-    static final int SURFACE_STATE_SUCCESS = 1;
-    static final int SURFACE_STATE_UPDATED = 2;
-
-    static final int FUNCTOR_PROCESS_DELAY = 4;
-
-    /**
-     * Number of frames to profile.
-     */
-    private static final int PROFILE_MAX_FRAMES = 128;
-
-    /**
-     * Number of floats per profiled frame.
-     */
-    private static final int PROFILE_FRAME_DATA_COUNT = 3;
-
-    private static final int PROFILE_DRAW_MARGIN = 0;
-    private static final int PROFILE_DRAW_WIDTH = 3;
-    private static final int[] PROFILE_DRAW_COLORS = { 0xcf3e66cc, 0xcfdc3912, 0xcfe69800 };
-    private static final int PROFILE_DRAW_CURRENT_FRAME_COLOR = 0xcf5faa4d;
-    private static final int PROFILE_DRAW_THRESHOLD_COLOR = 0xff5faa4d;
-    private static final int PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2;
-    private static final int PROFILE_DRAW_DP_PER_MS = 7;
-
-    private static final String[] VISUALIZERS = {
-            PROFILE_PROPERTY_VISUALIZE_BARS,
-    };
-
-    private static final String[] OVERDRAW = {
-            OVERDRAW_PROPERTY_SHOW,
-    };
-    private static final int GL_VERSION = 2;
-
-    static EGL10 sEgl;
-    static EGLDisplay sEglDisplay;
-    static EGLConfig sEglConfig;
-    static final Object[] sEglLock = new Object[0];
-    int mWidth = -1, mHeight = -1;
-
-    static final ThreadLocal<ManagedEGLContext> sEglContextStorage
-            = new ThreadLocal<ManagedEGLContext>();
-
-    EGLContext mEglContext;
-    Thread mEglThread;
-
-    EGLSurface mEglSurface;
-
-    GL mGl;
-    HardwareCanvas mCanvas;
-
-    String mName;
-
-    long mFrameCount;
-    Paint mDebugPaint;
-
-    static boolean sDirtyRegions;
-    static final boolean sDirtyRegionsRequested;
-    static {
-        String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        sDirtyRegions = "true".equalsIgnoreCase(dirtyProperty);
-        sDirtyRegionsRequested = sDirtyRegions;
-    }
-
-    boolean mDirtyRegionsEnabled;
-    boolean mUpdateDirtyRegions;
-
-    boolean mProfileEnabled;
-    int mProfileVisualizerType = -1;
-    float[] mProfileData;
-    ReentrantLock mProfileLock;
-    int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
-
-    GraphDataProvider mDebugDataProvider;
-    float[][] mProfileShapes;
-    Paint mProfilePaint;
-
-    boolean mDebugDirtyRegions;
-    int mDebugOverdraw = -1;
-
-    final boolean mTranslucent;
-
-    private boolean mDestroyed;
-
-    private final Rect mRedrawClip = new Rect();
-
-    private final int[] mSurfaceSize = new int[2];
-
-    private long mDrawDelta = Long.MAX_VALUE;
-
-    private GLES20Canvas mGlCanvas;
-
-    private DisplayMetrics mDisplayMetrics;
-
-    private static EGLSurface sPbuffer;
-    private static final Object[] sPbufferLock = new Object[0];
-
-    private List<HardwareLayer> mLayerUpdates = new ArrayList<HardwareLayer>();
-
-    private static class GLRendererEglContext extends ManagedEGLContext {
-        final Handler mHandler = new Handler();
-
-        public GLRendererEglContext(EGLContext context) {
-            super(context);
-        }
-
-        @Override
-        public void onTerminate(final EGLContext eglContext) {
-            // Make sure we do this on the correct thread.
-            if (mHandler.getLooper() != Looper.myLooper()) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        onTerminate(eglContext);
-                    }
-                });
-                return;
-            }
-
-            synchronized (sEglLock) {
-                if (sEgl == null) return;
-
-                if (EGLImpl.getInitCount(sEglDisplay) == 1) {
-                    usePbufferSurface(eglContext);
-                    GLES20Canvas.terminateCaches();
-
-                    sEgl.eglDestroyContext(sEglDisplay, eglContext);
-                    sEglContextStorage.set(null);
-                    sEglContextStorage.remove();
-
-                    sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
-                    sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
-                            EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-                    sEgl.eglReleaseThread();
-                    sEgl.eglTerminate(sEglDisplay);
-
-                    sEgl = null;
-                    sEglDisplay = null;
-                    sEglConfig = null;
-                    sPbuffer = null;
-                }
-            }
-        }
-    }
-
-    HardwareCanvas createCanvas() {
-        return mGlCanvas = new GLES20Canvas(mTranslucent);
-    }
-
-    ManagedEGLContext createManagedContext(EGLContext eglContext) {
-        return new GLRendererEglContext(mEglContext);
-    }
-
-    int[] getConfig(boolean dirtyRegions) {
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        final int stencilSize = GLES20Canvas.getStencilSize();
-        final int swapBehavior = dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
-
-        return new int[] {
-                EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
-                EGL_RED_SIZE, 8,
-                EGL_GREEN_SIZE, 8,
-                EGL_BLUE_SIZE, 8,
-                EGL_ALPHA_SIZE, 8,
-                EGL_DEPTH_SIZE, 0,
-                EGL_CONFIG_CAVEAT, EGL_NONE,
-                EGL_STENCIL_SIZE, stencilSize,
-                EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
-                EGL_NONE
-        };
-    }
-
-    void initCaches() {
-        if (GLES20Canvas.initCaches()) {
-            // Caches were (re)initialized, rebind atlas
-            initAtlas();
-        }
-    }
-
-    void initAtlas() {
-        IBinder binder = ServiceManager.getService("assetatlas");
-        if (binder == null) return;
-
-        IAssetAtlas atlas = IAssetAtlas.Stub.asInterface(binder);
-        try {
-            if (atlas.isCompatible(android.os.Process.myPpid())) {
-                GraphicBuffer buffer = atlas.getBuffer();
-                if (buffer != null) {
-                    long[] map = atlas.getMap();
-                    if (map != null) {
-                        GLES20Canvas.initAtlas(buffer, map);
-                    }
-                    // If IAssetAtlas is not the same class as the IBinder
-                    // we are using a remote service and we can safely
-                    // destroy the graphic buffer
-                    if (atlas.getClass() != binder.getClass()) {
-                        buffer.destroy();
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Could not acquire atlas", e);
-        }
-    }
-
-    boolean canDraw() {
-        return mGl != null && mCanvas != null && mGlCanvas != null;
-    }
-
-    int onPreDraw(Rect dirty) {
-        return mGlCanvas.onPreDraw(dirty);
-    }
-
-    void onPostDraw() {
-        mGlCanvas.onPostDraw();
-    }
-
-    void drawProfileData(View.AttachInfo attachInfo) {
-        if (mDebugDataProvider != null) {
-            final GraphDataProvider provider = mDebugDataProvider;
-            initProfileDrawData(attachInfo, provider);
-
-            final int height = provider.getVerticalUnitSize();
-            final int margin = provider.getHorizontaUnitMargin();
-            final int width = provider.getHorizontalUnitSize();
-
-            int x = 0;
-            int count = 0;
-            int current = 0;
-
-            final float[] data = provider.getData();
-            final int elementCount = provider.getElementCount();
-            final int graphType = provider.getGraphType();
-
-            int totalCount = provider.getFrameCount() * elementCount;
-            if (graphType == GraphDataProvider.GRAPH_TYPE_LINES) {
-                totalCount -= elementCount;
-            }
-
-            for (int i = 0; i < totalCount; i += elementCount) {
-                if (data[i] < 0.0f) break;
-
-                int index = count * 4;
-                if (i == provider.getCurrentFrame() * elementCount) current = index;
-
-                x += margin;
-                int x2 = x + width;
-
-                int y2 = mHeight;
-                int y1 = (int) (y2 - data[i] * height);
-
-                switch (graphType) {
-                    case GraphDataProvider.GRAPH_TYPE_BARS: {
-                        for (int j = 0; j < elementCount; j++) {
-                            //noinspection MismatchedReadAndWriteOfArray
-                            final float[] r = mProfileShapes[j];
-                            r[index] = x;
-                            r[index + 1] = y1;
-                            r[index + 2] = x2;
-                            r[index + 3] = y2;
-
-                            y2 = y1;
-                            if (j < elementCount - 1) {
-                                y1 = (int) (y2 - data[i + j + 1] * height);
-                            }
-                        }
-                    } break;
-                    case GraphDataProvider.GRAPH_TYPE_LINES: {
-                        for (int j = 0; j < elementCount; j++) {
-                            //noinspection MismatchedReadAndWriteOfArray
-                            final float[] r = mProfileShapes[j];
-                            r[index] = (x + x2) * 0.5f;
-                            r[index + 1] = index == 0 ? y1 : r[index - 1];
-                            r[index + 2] = r[index] + width;
-                            r[index + 3] = y1;
-
-                            y2 = y1;
-                            if (j < elementCount - 1) {
-                                y1 = (int) (y2 - data[i + j + 1] * height);
-                            }
-                        }
-                    } break;
-                }
-
-
-                x += width;
-                count++;
-            }
-
-            x += margin;
-
-            drawGraph(graphType, count);
-            drawCurrentFrame(graphType, current);
-            drawThreshold(x, height);
-        }
-    }
-
-    private void drawGraph(int graphType, int count) {
-        for (int i = 0; i < mProfileShapes.length; i++) {
-            mDebugDataProvider.setupGraphPaint(mProfilePaint, i);
-            switch (graphType) {
-                case GraphDataProvider.GRAPH_TYPE_BARS:
-                    mGlCanvas.drawRects(mProfileShapes[i], count * 4, mProfilePaint);
-                    break;
-                case GraphDataProvider.GRAPH_TYPE_LINES:
-                    mGlCanvas.drawLines(mProfileShapes[i], 0, count * 4, mProfilePaint);
-                    break;
-            }
-        }
-    }
-
-    private void drawCurrentFrame(int graphType, int index) {
-        if (index >= 0) {
-            mDebugDataProvider.setupCurrentFramePaint(mProfilePaint);
-            switch (graphType) {
-                case GraphDataProvider.GRAPH_TYPE_BARS:
-                    mGlCanvas.drawRect(mProfileShapes[2][index], mProfileShapes[2][index + 1],
-                            mProfileShapes[2][index + 2], mProfileShapes[0][index + 3],
-                            mProfilePaint);
-                    break;
-                case GraphDataProvider.GRAPH_TYPE_LINES:
-                    mGlCanvas.drawLine(mProfileShapes[2][index], mProfileShapes[2][index + 1],
-                            mProfileShapes[2][index], mHeight, mProfilePaint);
-                    break;
-            }
-        }
-    }
-
-    private void drawThreshold(int x, int height) {
-        float threshold = mDebugDataProvider.getThreshold();
-        if (threshold > 0.0f) {
-            mDebugDataProvider.setupThresholdPaint(mProfilePaint);
-            int y = (int) (mHeight - threshold * height);
-            mGlCanvas.drawLine(0.0f, y, x, y, mProfilePaint);
-        }
-    }
-
-    private void initProfileDrawData(View.AttachInfo attachInfo, GraphDataProvider provider) {
-        if (mProfileShapes == null) {
-            final int elementCount = provider.getElementCount();
-            final int frameCount = provider.getFrameCount();
-
-            mProfileShapes = new float[elementCount][];
-            for (int i = 0; i < elementCount; i++) {
-                mProfileShapes[i] = new float[frameCount * 4];
-            }
-
-            mProfilePaint = new Paint();
-        }
-
-        mProfilePaint.reset();
-        if (provider.getGraphType() == GraphDataProvider.GRAPH_TYPE_LINES) {
-            mProfilePaint.setAntiAlias(true);
-        }
-
-        if (mDisplayMetrics == null) {
-            mDisplayMetrics = new DisplayMetrics();
-        }
-
-        attachInfo.mDisplay.getMetrics(mDisplayMetrics);
-        provider.prepare(mDisplayMetrics);
-    }
-
-    @Override
-    void destroy(boolean full) {
-        try {
-            if (full && mCanvas != null) {
-                mCanvas = null;
-            }
-
-            if (!isEnabled() || mDestroyed) {
-                setEnabled(false);
-                return;
-            }
-
-            destroySurface();
-            setEnabled(false);
-
-            mDestroyed = true;
-            mGl = null;
-        } finally {
-            if (full && mGlCanvas != null) {
-                mGlCanvas = null;
-            }
-        }
-    }
-
-    @Override
-    void pushLayerUpdate(HardwareLayer layer) {
-        mLayerUpdates.add(layer);
-    }
-
-    @Override
-    void flushLayerUpdates() {
-        if (validate()) {
-            flushLayerChanges();
-            mGlCanvas.flushLayerUpdates();
-        }
-    }
-
-    @Override
-    HardwareLayer createTextureLayer() {
-        validate();
-        return HardwareLayer.createTextureLayer(this);
-    }
-
-    @Override
-    public HardwareLayer createDisplayListLayer(int width, int height) {
-        validate();
-        return HardwareLayer.createDisplayListLayer(this, width, height);
-    }
-
-    boolean hasContext() {
-        return sEgl != null && mEglContext != null
-                && mEglContext.equals(sEgl.eglGetCurrentContext());
-    }
-
-    @Override
-    void onLayerDestroyed(HardwareLayer layer) {
-        if (mGlCanvas != null) {
-            mGlCanvas.cancelLayerUpdate(layer);
-        }
-        mLayerUpdates.remove(layer);
-    }
-
-    @Override
-    public SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
-        return layer.createSurfaceTexture();
-    }
-
-    @Override
-    boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
-        if (!validate()) {
-            throw new IllegalStateException("Could not acquire hardware rendering context");
-        }
-        layer.flushChanges();
-        return GLES20Canvas.nCopyLayer(layer.getLayer(), bitmap.mNativeBitmap);
-    }
-
-    @Override
-    boolean safelyRun(Runnable action) {
-        boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
-
-        if (needsContext) {
-            GLRendererEglContext managedContext =
-                    (GLRendererEglContext) sEglContextStorage.get();
-            if (managedContext == null) return false;
-            usePbufferSurface(managedContext.getContext());
-        }
-
-        try {
-            action.run();
-        } finally {
-            if (needsContext) {
-                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
-                        EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    void invokeFunctor(long functor, boolean waitForCompletion) {
-        boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
-        boolean hasContext = !needsContext;
-
-        if (needsContext) {
-            GLRendererEglContext managedContext =
-                    (GLRendererEglContext) sEglContextStorage.get();
-            if (managedContext != null) {
-                usePbufferSurface(managedContext.getContext());
-                hasContext = true;
-            }
-        }
-
-        try {
-            nInvokeFunctor(functor, hasContext);
-        } finally {
-            if (needsContext) {
-                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
-                        EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            }
-        }
-    }
-
-    private static native void nInvokeFunctor(long functor, boolean hasContext);
-
-    @Override
-    void destroyHardwareResources(final View view) {
-        if (view != null) {
-            safelyRun(new Runnable() {
-                @Override
-                public void run() {
-                    if (mCanvas != null) {
-                        mCanvas.clearLayerUpdates();
-                    }
-                    destroyResources(view);
-                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
-                }
-            });
-        }
-    }
-
-    private static void destroyResources(View view) {
-        view.destroyHardwareResources();
-
-        if (view instanceof ViewGroup) {
-            ViewGroup group = (ViewGroup) view;
-
-            int count = group.getChildCount();
-            for (int i = 0; i < count; i++) {
-                destroyResources(group.getChildAt(i));
-            }
-        }
-    }
-
-    static void startTrimMemory(int level) {
-        if (sEgl == null || sEglConfig == null) return;
-
-        GLRendererEglContext managedContext =
-                (GLRendererEglContext) sEglContextStorage.get();
-        // We do not have OpenGL objects
-        if (managedContext == null) {
-            return;
-        } else {
-            usePbufferSurface(managedContext.getContext());
-        }
-
-        if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
-            GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
-        } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
-            GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
-        }
-    }
-
-    static void endTrimMemory() {
-        if (sEgl != null && sEglDisplay != null) {
-            sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-        }
-    }
-
-    private static void usePbufferSurface(EGLContext eglContext) {
-        synchronized (sPbufferLock) {
-            // Create a temporary 1x1 pbuffer so we have a context
-            // to clear our OpenGL objects
-            if (sPbuffer == null) {
-                sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] {
-                        EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
-                });
-            }
-        }
-        sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
-    }
-
-    GLRenderer(boolean translucent) {
-        mTranslucent = translucent;
-
-        loadSystemProperties();
-    }
-
-    @Override
-    void setOpaque(boolean opaque) {
-        // Not supported
-    }
-
-    @Override
-    boolean loadSystemProperties() {
-        boolean value;
-        boolean changed = false;
-
-        String profiling = SystemProperties.get(PROFILE_PROPERTY);
-        int graphType = search(VISUALIZERS, profiling);
-        value = graphType >= 0;
-
-        if (graphType != mProfileVisualizerType) {
-            changed = true;
-            mProfileVisualizerType = graphType;
-
-            mProfileShapes = null;
-            mProfilePaint = null;
-
-            if (value) {
-                mDebugDataProvider = new GraphDataProvider(graphType);
-            } else {
-                mDebugDataProvider = null;
-            }
-        }
-
-        // If on-screen profiling is not enabled, we need to check whether
-        // console profiling only is enabled
-        if (!value) {
-            value = Boolean.parseBoolean(profiling);
-        }
-
-        if (value != mProfileEnabled) {
-            changed = true;
-            mProfileEnabled = value;
-
-            if (mProfileEnabled) {
-                Log.d(LOG_TAG, "Profiling hardware renderer");
-
-                int maxProfileFrames = SystemProperties.getInt(PROFILE_MAXFRAMES_PROPERTY,
-                        PROFILE_MAX_FRAMES);
-                mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT];
-                for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
-                    mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
-                }
-
-                mProfileLock = new ReentrantLock();
-            } else {
-                mProfileData = null;
-                mProfileLock = null;
-                mProfileVisualizerType = -1;
-            }
-
-            mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
-        }
-
-        value = SystemProperties.getBoolean(DEBUG_DIRTY_REGIONS_PROPERTY, false);
-        if (value != mDebugDirtyRegions) {
-            changed = true;
-            mDebugDirtyRegions = value;
-
-            if (mDebugDirtyRegions) {
-                Log.d(LOG_TAG, "Debugging dirty regions");
-            }
-        }
-
-        String overdraw = SystemProperties.get(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY);
-        int debugOverdraw = search(OVERDRAW, overdraw);
-        if (debugOverdraw != mDebugOverdraw) {
-            changed = true;
-            mDebugOverdraw = debugOverdraw;
-        }
-
-        if (loadProperties()) {
-            changed = true;
-        }
-
-        return changed;
-    }
-
-    private static int search(String[] values, String value) {
-        for (int i = 0; i < values.length; i++) {
-            if (values[i].equals(value)) return i;
-        }
-        return -1;
-    }
-
-    @Override
-    void dumpGfxInfo(PrintWriter pw, FileDescriptor fd) {
-        if (mProfileEnabled) {
-            pw.printf("\n\tDraw\tProcess\tExecute\n");
-
-            mProfileLock.lock();
-            try {
-                for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
-                    if (mProfileData[i] < 0) {
-                        break;
-                    }
-                    pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1],
-                            mProfileData[i + 2]);
-                    mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
-                }
-                mProfileCurrentFrame = mProfileData.length;
-            } finally {
-                mProfileLock.unlock();
-            }
-        }
-    }
-
-    /**
-     * Indicates whether this renderer instance can track and update dirty regions.
-     */
-    boolean hasDirtyRegions() {
-        return mDirtyRegionsEnabled;
-    }
-
-    /**
-     * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
-     * is invoked and the requested flag is turned off. The error code is
-     * also logged as a warning.
-     */
-    void checkEglErrors() {
-        if (isEnabled()) {
-            checkEglErrorsForced();
-        }
-    }
-
-    private void checkEglErrorsForced() {
-        int error = sEgl.eglGetError();
-        if (error != EGL_SUCCESS) {
-            // something bad has happened revert to
-            // normal rendering.
-            Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
-            fallback(error != EGL11.EGL_CONTEXT_LOST);
-        }
-    }
-
-    private void fallback(boolean fallback) {
-        destroy(true);
-        if (fallback) {
-            // we'll try again if it was context lost
-            setRequested(false);
-            Log.w(LOG_TAG, "Mountain View, we've had a problem here. "
-                    + "Switching back to software rendering.");
-        }
-    }
-
-    @Override
-    boolean initialize(Surface surface) throws OutOfResourcesException {
-        if (isRequested() && !isEnabled()) {
-            boolean contextCreated = initializeEgl();
-            mGl = createEglSurface(surface);
-            mDestroyed = false;
-
-            if (mGl != null) {
-                int err = sEgl.eglGetError();
-                if (err != EGL_SUCCESS) {
-                    destroy(true);
-                    setRequested(false);
-                } else {
-                    if (mCanvas == null) {
-                        mCanvas = createCanvas();
-                    }
-                    setEnabled(true);
-
-                    if (contextCreated) {
-                        initAtlas();
-                    }
-                }
-
-                return mCanvas != null;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    void updateSurface(Surface surface) throws OutOfResourcesException {
-        if (isRequested() && isEnabled()) {
-            createEglSurface(surface);
-        }
-    }
-
-    @Override
-    void pauseSurface(Surface surface) {
-        // No-op
-    }
-
-    boolean initializeEgl() {
-        synchronized (sEglLock) {
-            if (sEgl == null && sEglConfig == null) {
-                sEgl = (EGL10) EGLContext.getEGL();
-
-                // Get to the default display.
-                sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
-                if (sEglDisplay == EGL_NO_DISPLAY) {
-                    throw new RuntimeException("eglGetDisplay failed "
-                            + GLUtils.getEGLErrorString(sEgl.eglGetError()));
-                }
-
-                // We can now initialize EGL for that display
-                int[] version = new int[2];
-                if (!sEgl.eglInitialize(sEglDisplay, version)) {
-                    throw new RuntimeException("eglInitialize failed " +
-                            GLUtils.getEGLErrorString(sEgl.eglGetError()));
-                }
-
-                checkEglErrorsForced();
-
-                sEglConfig = loadEglConfig();
-            }
-        }
-
-        ManagedEGLContext managedContext = sEglContextStorage.get();
-        mEglContext = managedContext != null ? managedContext.getContext() : null;
-        mEglThread = Thread.currentThread();
-
-        if (mEglContext == null) {
-            mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
-            sEglContextStorage.set(createManagedContext(mEglContext));
-            return true;
-        }
-
-        return false;
-    }
-
-    private EGLConfig loadEglConfig() {
-        EGLConfig eglConfig = chooseEglConfig();
-        if (eglConfig == null) {
-            // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
-            if (sDirtyRegions) {
-                sDirtyRegions = false;
-                eglConfig = chooseEglConfig();
-                if (eglConfig == null) {
-                    throw new RuntimeException("eglConfig not initialized");
-                }
-            } else {
-                throw new RuntimeException("eglConfig not initialized");
-            }
-        }
-        return eglConfig;
-    }
-
-    private EGLConfig chooseEglConfig() {
-        EGLConfig[] configs = new EGLConfig[1];
-        int[] configsCount = new int[1];
-        int[] configSpec = getConfig(sDirtyRegions);
-
-        // Debug
-        final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, "");
-        if ("all".equalsIgnoreCase(debug)) {
-            sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount);
-
-            EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]];
-            sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs,
-                    configsCount[0], configsCount);
-
-            for (EGLConfig config : debugConfigs) {
-                printConfig(config);
-            }
-        }
-
-        if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
-            throw new IllegalArgumentException("eglChooseConfig failed " +
-                    GLUtils.getEGLErrorString(sEgl.eglGetError()));
-        } else if (configsCount[0] > 0) {
-            if ("choice".equalsIgnoreCase(debug)) {
-                printConfig(configs[0]);
-            }
-            return configs[0];
-        }
-
-        return null;
-    }
-
-    private static void printConfig(EGLConfig config) {
-        int[] value = new int[1];
-
-        Log.d(LOG_TAG, "EGL configuration " + config + ":");
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value);
-        Log.d(LOG_TAG, "  RED_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value);
-        Log.d(LOG_TAG, "  GREEN_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value);
-        Log.d(LOG_TAG, "  BLUE_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value);
-        Log.d(LOG_TAG, "  ALPHA_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value);
-        Log.d(LOG_TAG, "  DEPTH_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
-        Log.d(LOG_TAG, "  STENCIL_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLE_BUFFERS, value);
-        Log.d(LOG_TAG, "  SAMPLE_BUFFERS = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLES, value);
-        Log.d(LOG_TAG, "  SAMPLES = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
-        Log.d(LOG_TAG, "  SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_CONFIG_CAVEAT, value);
-        Log.d(LOG_TAG, "  CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0]));
-    }
-
-    GL createEglSurface(Surface surface) throws OutOfResourcesException {
-        // Check preconditions.
-        if (sEgl == null) {
-            throw new RuntimeException("egl not initialized");
-        }
-        if (sEglDisplay == null) {
-            throw new RuntimeException("eglDisplay not initialized");
-        }
-        if (sEglConfig == null) {
-            throw new RuntimeException("eglConfig not initialized");
-        }
-        if (Thread.currentThread() != mEglThread) {
-            throw new IllegalStateException("HardwareRenderer cannot be used "
-                    + "from multiple threads");
-        }
-
-        // In case we need to destroy an existing surface
-        destroySurface();
-
-        // Create an EGL surface we can render into.
-        if (!createSurface(surface)) {
-            return null;
-        }
-
-        initCaches();
-
-        return mEglContext.getGL();
-    }
-
-    private void enableDirtyRegions() {
-        // If mDirtyRegions is set, this means we have an EGL configuration
-        // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
-        if (sDirtyRegions) {
-            if (!(mDirtyRegionsEnabled = preserveBackBuffer())) {
-                Log.w(LOG_TAG, "Backbuffer cannot be preserved");
-            }
-        } else if (sDirtyRegionsRequested) {
-            // If mDirtyRegions is not set, our EGL configuration does not
-            // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
-            // swap behavior might be EGL_BUFFER_PRESERVED, which means we
-            // want to set mDirtyRegions. We try to do this only if dirty
-            // regions were initially requested as part of the device
-            // configuration (see RENDER_DIRTY_REGIONS)
-            mDirtyRegionsEnabled = isBackBufferPreserved();
-        }
-    }
-
-    EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-        final int[] attribs = { EGL14.EGL_CONTEXT_CLIENT_VERSION, GL_VERSION, EGL_NONE };
-
-        EGLContext context = egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
-                attribs);
-        if (context == null || context == EGL_NO_CONTEXT) {
-            //noinspection ConstantConditions
-            throw new IllegalStateException(
-                    "Could not create an EGL context. eglCreateContext failed with error: " +
-                    GLUtils.getEGLErrorString(sEgl.eglGetError()));
-        }
-
-        return context;
-    }
-
-    void destroySurface() {
-        if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
-            if (mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
-                sEgl.eglMakeCurrent(sEglDisplay,
-                        EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            }
-            sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
-            mEglSurface = null;
-        }
-    }
-
-    @Override
-    void invalidate(Surface surface) {
-        // Cancels any existing buffer to ensure we'll get a buffer
-        // of the right size before we call eglSwapBuffers
-        sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-        if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
-            sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
-            mEglSurface = null;
-            setEnabled(false);
-        }
-
-        if (surface.isValid()) {
-            if (!createSurface(surface)) {
-                return;
-            }
-
-            mUpdateDirtyRegions = true;
-
-            if (mCanvas != null) {
-                setEnabled(true);
-            }
-        }
-    }
-
-    private boolean createSurface(Surface surface) {
-        mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, surface, null);
-
-        if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
-            int error = sEgl.eglGetError();
-            if (error == EGL_BAD_NATIVE_WINDOW) {
-                Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
-                return false;
-            }
-            throw new RuntimeException("createWindowSurface failed "
-                    + GLUtils.getEGLErrorString(error));
-        }
-
-        if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-            throw new IllegalStateException("eglMakeCurrent failed " +
-                    GLUtils.getEGLErrorString(sEgl.eglGetError()));
-        }
-
-        enableDirtyRegions();
-
-        return true;
-    }
-
-    boolean validate() {
-        return checkRenderContext() != SURFACE_STATE_ERROR;
-    }
-
-    @Override
-    void setup(int width, int height, float lightX, float lightY, float lightZ, float lightRadius) {
-        if (validate()) {
-            mCanvas.setViewport(width, height);
-            mCanvas.initializeLight(lightX, lightY, lightZ, lightRadius);
-            mWidth = width;
-            mHeight = height;
-        }
-    }
-
-    @Override
-    int getWidth() {
-        return mWidth;
-    }
-
-    @Override
-    int getHeight() {
-        return mHeight;
-    }
-
-    @Override
-    void setName(String name) {
-        mName = name;
-    }
-
-    @Override
-    void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
-            Rect dirty) {
-        if (canDraw()) {
-            if (!hasDirtyRegions()) {
-                dirty = null;
-            }
-            attachInfo.mIgnoreDirtyState = true;
-            attachInfo.mDrawingTime = SystemClock.uptimeMillis();
-
-            view.mPrivateFlags |= View.PFLAG_DRAWN;
-
-            // We are already on the correct thread
-            final int surfaceState = checkRenderContextUnsafe();
-            if (surfaceState != SURFACE_STATE_ERROR) {
-                HardwareCanvas canvas = mCanvas;
-
-                if (mProfileEnabled) {
-                    mProfileLock.lock();
-                }
-
-                dirty = beginFrame(canvas, dirty, surfaceState);
-
-                RenderNode displayList = buildDisplayList(view, canvas);
-
-                flushLayerChanges();
-
-                // buildDisplayList() calls into user code which can cause
-                // an eglMakeCurrent to happen with a different surface/context.
-                // We must therefore check again here.
-                if (checkRenderContextUnsafe() == SURFACE_STATE_ERROR) {
-                    return;
-                }
-
-                int saveCount = 0;
-                int status = RenderNode.STATUS_DONE;
-
-                long start = getSystemTime();
-                try {
-                    status = prepareFrame(dirty);
-
-                    saveCount = canvas.save();
-                    callbacks.onHardwarePreDraw(canvas);
-
-                    if (displayList != null) {
-                        status |= drawDisplayList(canvas, displayList, status);
-                    } else {
-                        // Shouldn't reach here
-                        view.draw(canvas);
-                    }
-                } catch (Exception e) {
-                    Log.e(LOG_TAG, "An error has occurred while drawing:", e);
-                } finally {
-                    callbacks.onHardwarePostDraw(canvas);
-                    canvas.restoreToCount(saveCount);
-                    view.mRecreateDisplayList = false;
-
-                    mDrawDelta = getSystemTime() - start;
-
-                    if (mDrawDelta > 0) {
-                        mFrameCount++;
-
-                        debugDirtyRegions(dirty, canvas);
-                        drawProfileData(attachInfo);
-                    }
-                }
-
-                onPostDraw();
-
-                swapBuffers(status);
-
-                if (mProfileEnabled) {
-                    mProfileLock.unlock();
-                }
-
-                attachInfo.mIgnoreDirtyState = false;
-            }
-        }
-    }
-
-    private void flushLayerChanges() {
-        // Loop through and apply any pending layer changes
-        for (int i = 0; i < mLayerUpdates.size(); i++) {
-            HardwareLayer layer = mLayerUpdates.get(i);
-            layer.flushChanges();
-            if (!layer.isValid()) {
-                // The layer was removed from mAttachedLayers, rewind i by 1
-                // Note that this shouldn't actually happen as View.getHardwareLayer()
-                // is already flushing for error checking reasons
-                i--;
-            } else if (layer.hasDisplayList()) {
-                mCanvas.pushLayerUpdate(layer);
-            }
-        }
-        mLayerUpdates.clear();
-    }
-
-    @Override
-    void fence() {
-        // Everything is immediate, so this is a no-op
-    }
-
-    private RenderNode buildDisplayList(View view, HardwareCanvas canvas) {
-        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
-                == View.PFLAG_INVALIDATED;
-        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
-
-        long buildDisplayListStartTime = startBuildDisplayListProfiling();
-        canvas.clearLayerUpdates();
-
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
-        RenderNode renderNode = view.getDisplayList();
-        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-
-        endBuildDisplayListProfiling(buildDisplayListStartTime);
-
-        return renderNode;
-    }
-
-    private Rect beginFrame(HardwareCanvas canvas, Rect dirty, int surfaceState) {
-        // We had to change the current surface and/or context, redraw everything
-        if (surfaceState == SURFACE_STATE_UPDATED) {
-            dirty = null;
-            beginFrame(null);
-        } else {
-            int[] size = mSurfaceSize;
-            beginFrame(size);
-
-            if (size[1] != mHeight || size[0] != mWidth) {
-                mWidth = size[0];
-                mHeight = size[1];
-
-                canvas.setViewport(mWidth, mHeight);
-
-                dirty = null;
-            }
-        }
-
-        if (mDebugDataProvider != null) dirty = null;
-
-        return dirty;
-    }
-
-    private long startBuildDisplayListProfiling() {
-        if (mProfileEnabled) {
-            mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT;
-            if (mProfileCurrentFrame >= mProfileData.length) {
-                mProfileCurrentFrame = 0;
-            }
-
-            return System.nanoTime();
-        }
-        return 0;
-    }
-
-    private void endBuildDisplayListProfiling(long getDisplayListStartTime) {
-        if (mProfileEnabled) {
-            long now = System.nanoTime();
-            float total = (now - getDisplayListStartTime) * 0.000001f;
-            //noinspection PointlessArithmeticExpression
-            mProfileData[mProfileCurrentFrame] = total;
-        }
-    }
-
-    private int prepareFrame(Rect dirty) {
-        int status;
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
-        try {
-            status = onPreDraw(dirty);
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
-        return status;
-    }
-
-    private int drawDisplayList(HardwareCanvas canvas, RenderNode displayList,
-            int status) {
-
-        long drawDisplayListStartTime = 0;
-        if (mProfileEnabled) {
-            drawDisplayListStartTime = System.nanoTime();
-        }
-
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList");
-        nPrepareTree(displayList.getNativeDisplayList());
-        try {
-            status |= canvas.drawDisplayList(displayList, mRedrawClip,
-                    RenderNode.FLAG_CLIP_CHILDREN);
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
-
-        if (mProfileEnabled) {
-            long now = System.nanoTime();
-            float total = (now - drawDisplayListStartTime) * 0.000001f;
-            mProfileData[mProfileCurrentFrame + 1] = total;
-        }
-
-        return status;
-    }
-
-    private void swapBuffers(int status) {
-        if ((status & RenderNode.STATUS_DREW) == RenderNode.STATUS_DREW) {
-            long eglSwapBuffersStartTime = 0;
-            if (mProfileEnabled) {
-                eglSwapBuffersStartTime = System.nanoTime();
-            }
-
-            sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
-
-            if (mProfileEnabled) {
-                long now = System.nanoTime();
-                float total = (now - eglSwapBuffersStartTime) * 0.000001f;
-                mProfileData[mProfileCurrentFrame + 2] = total;
-            }
-
-            checkEglErrors();
-        }
-    }
-
-    private void debugDirtyRegions(Rect dirty, HardwareCanvas canvas) {
-        if (mDebugDirtyRegions) {
-            if (mDebugPaint == null) {
-                mDebugPaint = new Paint();
-                mDebugPaint.setColor(0x7fff0000);
-            }
-
-            if (dirty != null && (mFrameCount & 1) == 0) {
-                canvas.drawRect(dirty, mDebugPaint);
-            }
-        }
-    }
-
-    /**
-     * Ensures the current EGL context and surface are the ones we expect.
-     * This method throws an IllegalStateException if invoked from a thread
-     * that did not initialize EGL.
-     *
-     * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
-     *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
-     *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
-     *
-     * @see #checkRenderContextUnsafe()
-     */
-    int checkRenderContext() {
-        if (mEglThread != Thread.currentThread()) {
-            throw new IllegalStateException("Hardware acceleration can only be used with a " +
-                    "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
-                    "Current thread: " + Thread.currentThread());
-        }
-
-        return checkRenderContextUnsafe();
-    }
-
-    /**
-     * Ensures the current EGL context and surface are the ones we expect.
-     * This method does not check the current thread.
-     *
-     * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
-     *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
-     *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
-     *
-     * @see #checkRenderContext()
-     */
-    private int checkRenderContextUnsafe() {
-        if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) ||
-                !mEglContext.equals(sEgl.eglGetCurrentContext())) {
-            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                Log.e(LOG_TAG, "eglMakeCurrent failed " +
-                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
-                fallback(true);
-                return SURFACE_STATE_ERROR;
-            } else {
-                if (mUpdateDirtyRegions) {
-                    enableDirtyRegions();
-                    mUpdateDirtyRegions = false;
-                }
-                return SURFACE_STATE_UPDATED;
-            }
-        }
-        return SURFACE_STATE_SUCCESS;
-    }
-
-    private static int dpToPx(int dp, float density) {
-        return (int) (dp * density + 0.5f);
-    }
-
-    static native boolean loadProperties();
-
-    static native void setupShadersDiskCache(String cacheFile);
-
-    /**
-     * Notifies EGL that the frame is about to be rendered.
-     * @param size
-     */
-    static native void beginFrame(int[] size);
-
-    /**
-     * Returns the current system time according to the renderer.
-     * This method is used for debugging only and should not be used
-     * as a clock.
-     */
-    static native long getSystemTime();
-
-    /**
-     * Preserves the back buffer of the current surface after a buffer swap.
-     * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current
-     * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL
-     * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT.
-     *
-     * @return True if the swap behavior was successfully changed,
-     *         false otherwise.
-     */
-    static native boolean preserveBackBuffer();
-
-    /**
-     * Indicates whether the current surface preserves its back buffer
-     * after a buffer swap.
-     *
-     * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED,
-     *         false otherwise
-     */
-    static native boolean isBackBufferPreserved();
-
-    static native void nDestroyLayer(long layerPtr);
-
-    private static native void nPrepareTree(long displayListPtr);
-
-    class GraphDataProvider {
-        /**
-         * Draws the graph as bars. Frame elements are stacked on top of
-         * each other.
-         */
-        public static final int GRAPH_TYPE_BARS = 0;
-        /**
-         * Draws the graph as lines. The number of series drawn corresponds
-         * to the number of elements.
-         */
-        public static final int GRAPH_TYPE_LINES = 1;
-
-        private final int mGraphType;
-
-        private int mVerticalUnit;
-        private int mHorizontalUnit;
-        private int mHorizontalMargin;
-        private int mThresholdStroke;
-
-        public GraphDataProvider(int graphType) {
-            mGraphType = graphType;
-        }
-
-        void prepare(DisplayMetrics metrics) {
-            final float density = metrics.density;
-
-            mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density);
-            mHorizontalUnit = dpToPx(PROFILE_DRAW_WIDTH, density);
-            mHorizontalMargin = dpToPx(PROFILE_DRAW_MARGIN, density);
-            mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density);
-        }
-
-        int getGraphType() {
-            return mGraphType;
-        }
-
-        int getVerticalUnitSize() {
-            return mVerticalUnit;
-        }
-
-        int getHorizontalUnitSize() {
-            return mHorizontalUnit;
-        }
-
-        int getHorizontaUnitMargin() {
-            return mHorizontalMargin;
-        }
-
-        float[] getData() {
-            return mProfileData;
-        }
-
-        float getThreshold() {
-            return 16;
-        }
-
-        int getFrameCount() {
-            return mProfileData.length / PROFILE_FRAME_DATA_COUNT;
-        }
-
-        int getElementCount() {
-            return PROFILE_FRAME_DATA_COUNT;
-        }
-
-        int getCurrentFrame() {
-            return mProfileCurrentFrame / PROFILE_FRAME_DATA_COUNT;
-        }
-
-        void setupGraphPaint(Paint paint, int elementIndex) {
-            paint.setColor(PROFILE_DRAW_COLORS[elementIndex]);
-            if (mGraphType == GRAPH_TYPE_LINES) paint.setStrokeWidth(mThresholdStroke);
-        }
-
-        void setupThresholdPaint(Paint paint) {
-            paint.setColor(PROFILE_DRAW_THRESHOLD_COLOR);
-            paint.setStrokeWidth(mThresholdStroke);
-        }
-
-        void setupCurrentFramePaint(Paint paint) {
-            paint.setColor(PROFILE_DRAW_CURRENT_FRAME_COLOR);
-            if (mGraphType == GRAPH_TYPE_LINES) paint.setStrokeWidth(mThresholdStroke);
-        }
-    }
-}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 9568760..b8e7d8c 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -110,48 +110,6 @@
         return RenderNode.STATUS_DONE;
     }
 
-    /**
-     * Indicates that the specified layer must be updated as soon as possible.
-     *
-     * @param layer The layer to update
-     *
-     * @see #clearLayerUpdates()
-     *
-     * @hide
-     */
-    abstract void pushLayerUpdate(HardwareLayer layer);
-
-    /**
-     * Cancels a queued layer update. If the specified layer was not
-     * queued for update, this method has no effect.
-     *
-     * @param layer The layer whose update to cancel
-     *
-     * @see #pushLayerUpdate(HardwareLayer)
-     * @see #clearLayerUpdates()
-     *
-     * @hide
-     */
-    abstract void cancelLayerUpdate(HardwareLayer layer);
-
-    /**
-     * Immediately executes all enqueued layer updates.
-     *
-     * @see #pushLayerUpdate(HardwareLayer)
-     *
-     * @hide
-     */
-    abstract void flushLayerUpdates();
-
-    /**
-     * Removes all enqueued layer updates.
-     *
-     * @see #pushLayerUpdate(HardwareLayer)
-     *
-     * @hide
-     */
-    abstract void clearLayerUpdates();
-
     public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
             CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
 }
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 652bcd2..6acb134 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -172,24 +172,6 @@
         });
     }
 
-    /**
-     * This exists to minimize impact into the current HardwareLayer paths as
-     * some of the specifics of how to handle error cases in the fully
-     * deferred model will work
-     */
-    @Deprecated
-    public void flushChanges() {
-        if (HardwareRenderer.sUseRenderThread) {
-            // Not supported, don't try.
-            return;
-        }
-
-        boolean success = nFlushChanges(mFinalizer.get());
-        if (!success) {
-            destroy();
-        }
-    }
-
     public long getLayer() {
         return nGetLayer(mFinalizer.get());
     }
@@ -216,33 +198,14 @@
         return st;
     }
 
-    /**
-     * This should only be used by HardwareRenderer! Do not call directly
-     */
-    static HardwareLayer createTextureLayer(HardwareRenderer renderer) {
-        return new HardwareLayer(renderer, nCreateTextureLayer(), LAYER_TYPE_TEXTURE);
-    }
-
     static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
         return new HardwareLayer(renderer, layer, LAYER_TYPE_TEXTURE);
     }
 
-    /**
-     * This should only be used by HardwareRenderer! Do not call directly
-     */
-    static HardwareLayer createDisplayListLayer(HardwareRenderer renderer,
-            int width, int height) {
-        return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_DISPLAY_LIST);
-    }
-
     static HardwareLayer adoptDisplayListLayer(HardwareRenderer renderer, long layer) {
         return new HardwareLayer(renderer, layer, LAYER_TYPE_DISPLAY_LIST);
     }
 
-    /** This also creates the underlying layer */
-    private static native long nCreateTextureLayer();
-    private static native long nCreateRenderLayer(int width, int height);
-
     private static native void nOnTextureDestroyed(long layerUpdater);
 
     private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index d71de9f..d67c974 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -171,9 +171,6 @@
      */
     public static boolean sSystemRendererDisabled = false;
 
-    /** @hide */
-    public static boolean sUseRenderThread = true;
-
     private boolean mEnabled;
     private boolean mRequested = true;
 
@@ -309,7 +306,7 @@
      * @hide
      */
     public static void setupDiskCache(File cacheDir) {
-        GLRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
+        ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
     }
 
     /**
@@ -469,11 +466,7 @@
     static HardwareRenderer create(boolean translucent) {
         HardwareRenderer renderer = null;
         if (GLES20Canvas.isAvailable()) {
-            if (sUseRenderThread) {
-                renderer = new ThreadedRenderer(translucent);
-            } else {
-                renderer = new GLRenderer(translucent);
-            }
+            renderer = new ThreadedRenderer(translucent);
         }
         return renderer;
     }
@@ -500,7 +493,7 @@
      *              see {@link android.content.ComponentCallbacks}
      */
     static void startTrimMemory(int level) {
-        GLRenderer.startTrimMemory(level);
+        ThreadedRenderer.startTrimMemory(level);
     }
 
     /**
@@ -508,7 +501,7 @@
      * cleanup special resources used by the memory trimming process.
      */
     static void endTrimMemory() {
-        GLRenderer.endTrimMemory();
+        ThreadedRenderer.endTrimMemory();
     }
 
     /**
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index e918119..4979059 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -219,6 +219,15 @@
         return mTarget;
     }
 
+    /**
+     * WARNING: May only be called once!!!
+     * TODO: Fix above -_-
+     */
+    public void setStartValue(float startValue) {
+        checkMutable();
+        nSetStartValue(mNativePtr.get(), startValue);
+    }
+
     @Override
     public void setStartDelay(long startDelay) {
         checkMutable();
@@ -282,11 +291,12 @@
     }
 
     private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            int property, float deltaValue);
+            int property, float finalValue);
     private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            long canvasProperty, float deltaValue);
+            long canvasProperty, float finalValue);
     private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
-            long canvasProperty, int paintField, float deltaValue);
+            long canvasProperty, int paintField, float finalValue);
+    private static native void nSetStartValue(long nativePtr, float startValue);
     private static native void nSetDuration(long nativePtr, long duration);
     private static native long nGetDuration(long nativePtr);
     private static native void nSetStartDelay(long nativePtr, long startDelay);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 11db996..9b3ef7f 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -331,6 +331,14 @@
         }
     }
 
+    static void startTrimMemory(int level) {
+        // TODO
+    }
+
+    static void endTrimMemory() {
+        // TODO
+    }
+
     private static class AtlasInitializer {
         static AtlasInitializer sInstance = new AtlasInitializer();
 
@@ -367,6 +375,8 @@
         }
     }
 
+    static native void setupShadersDiskCache(String cacheFile);
+
     private static native void nSetAtlas(GraphicBuffer buffer, long[] map);
 
     private static native long nCreateRootRenderNode();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ce266d7..622fa8c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13593,12 +13593,6 @@
                 }
             }
 
-            // The layer is not valid if the underlying GPU resources cannot be allocated
-            mHardwareLayer.flushChanges();
-            if (!mHardwareLayer.isValid()) {
-                return null;
-            }
-
             mHardwareLayer.setLayerPaint(mLayerPaint);
             RenderNode displayList = mHardwareLayer.startRecording();
             updateDisplayListIfDirty(displayList, true);
@@ -16197,6 +16191,20 @@
     }
 
     /**
+     * Set this view's optical insets.
+     *
+     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
+     * property. Views that compute their own optical insets should call it as part of measurement.
+     * This method does not request layout. If you are setting optical insets outside of
+     * measure/layout itself you will want to call requestLayout() yourself.
+     * </p>
+     * @hide
+     */
+    public void setOpticalInsets(Insets insets) {
+        mLayoutInsets = insets;
+    }
+
+    /**
      * Changes the selection state of this view. A view can be selected or not.
      * Note that selection is not the same as focus. Views are typically
      * selected in the context of an AdapterView like ListView or GridView;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ac25b57..f3d1e3c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -716,17 +716,6 @@
 
             if (!HardwareRenderer.sRendererDisabled || (HardwareRenderer.sSystemRendererDisabled
                     && forceHwAccelerated)) {
-                if (!HardwareRenderer.sUseRenderThread) {
-                    // TODO: Delete
-                    // Don't enable hardware acceleration when we're not on the main thread
-                    if (!HardwareRenderer.sSystemRendererDisabled &&
-                            Looper.getMainLooper() != Looper.myLooper()) {
-                        Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware "
-                                + "acceleration outside of the main thread, aborting");
-                        return;
-                    }
-                }
-
                 if (mAttachInfo.mHardwareRenderer != null) {
                     mAttachInfo.mHardwareRenderer.destroy(true);
                 }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index eedacb5..572302a4 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -664,7 +664,7 @@
                 InputStream stream = null;
                 try {
                     stream = mContext.getContentResolver().openInputStream(mUri);
-                    d = Drawable.createFromStreamThemed(stream, null, mContext.getTheme());
+                    d = Drawable.createFromStream(stream, null);
                 } catch (Exception e) {
                     Log.w("ImageView", "Unable to open content: " + mUri, e);
                 } finally {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 0c3715d..b49938c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -357,9 +357,8 @@
                     Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
             shapeDrawable.getPaint().setShader(bitmapShader);
 
-            // Ensure the color filter and tint are propagated.
-            shapeDrawable.setTint(bitmap.getTint());
-            shapeDrawable.setTintMode(bitmap.getTintMode());
+            // Ensure the tint and filter are propagated in the correct order.
+            shapeDrawable.setTint(bitmap.getTint(), bitmap.getTintMode());
             shapeDrawable.setColorFilter(bitmap.getColorFilter());
 
             return clip ? new ClipDrawable(
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index 02033012..c8917e0 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -574,7 +574,7 @@
                     throw new FileNotFoundException("Failed to open " + uri);
                 }
                 try {
-                    return Drawable.createFromStreamThemed(stream, null, mContext.getTheme());
+                    return Drawable.createFromStream(stream, null);
                 } finally {
                     try {
                         stream.close();
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index 03d3b22..77f0dec 100644
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -25,16 +25,18 @@
 interface IMediaContainerService {
     String copyResourceToContainer(in Uri packageURI, String containerId, String key,
             String resFileName, String publicResFileName, boolean isExternal,
-            boolean isForwardLocked);
+            boolean isForwardLocked, in String abiOverride);
     int copyResource(in Uri packageURI, in ContainerEncryptionParams encryptionParams,
             in ParcelFileDescriptor outStream);
-    PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold);
+    PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold,
+            in String abiOverride);
     boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold);
-    boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked);
+    boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in String abiOverride);
     ObbInfo getObbInfo(in String filename);
     long calculateDirectorySize(in String directory);
     /** Return file system stats: [0] is total bytes, [1] is available bytes */
     long[] getFileSystemStats(in String path);
     void clearDirectory(in String directory);
-    long calculateInstalledSize(in String packagePath, boolean isForwardLocked);
+    long calculateInstalledSize(in String packagePath, boolean isForwardLocked,
+            in String abiOverride);
 }
diff --git a/core/java/com/android/internal/backup/BackupConstants.java b/core/java/com/android/internal/backup/BackupConstants.java
deleted file mode 100644
index 4c276b7..0000000
--- a/core/java/com/android/internal/backup/BackupConstants.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.backup;
-
-/**
- * Constants used internally between the backup manager and its transports
- */
-public class BackupConstants {
-    public static final int TRANSPORT_OK = 0;
-    public static final int TRANSPORT_ERROR = 1;
-    public static final int TRANSPORT_NOT_INITIALIZED = 2;
-    public static final int AGENT_ERROR = 3;
-    public static final int AGENT_UNKNOWN = 4;
-}
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index f2b29ef6..7292116 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -104,7 +104,7 @@
     public int initializeDevice() {
         if (DEBUG) Log.v(TAG, "wiping all data");
         deleteContents(mCurrentSetDir);
-        return BackupConstants.TRANSPORT_OK;
+        return BackupTransport.TRANSPORT_OK;
     }
 
     public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) {
@@ -166,7 +166,7 @@
                         entity.write(buf, 0, dataSize);
                     } catch (IOException e) {
                         Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath());
-                        return BackupConstants.TRANSPORT_ERROR;
+                        return BackupTransport.TRANSPORT_ERROR;
                     } finally {
                         entity.close();
                     }
@@ -174,11 +174,11 @@
                     entityFile.delete();
                 }
             }
-            return BackupConstants.TRANSPORT_OK;
+            return BackupTransport.TRANSPORT_OK;
         } catch (IOException e) {
             // oops, something went wrong.  abort the operation and return error.
             Log.v(TAG, "Exception reading backup input:", e);
-            return BackupConstants.TRANSPORT_ERROR;
+            return BackupTransport.TRANSPORT_ERROR;
         }
     }
 
@@ -208,12 +208,12 @@
             }
             packageDir.delete();
         }
-        return BackupConstants.TRANSPORT_OK;
+        return BackupTransport.TRANSPORT_OK;
     }
 
     public int finishBackup() {
         if (DEBUG) Log.v(TAG, "finishBackup()");
-        return BackupConstants.TRANSPORT_OK;
+        return BackupTransport.TRANSPORT_OK;
     }
 
     // Restore handling
@@ -249,7 +249,7 @@
         mRestorePackage = -1;
         mRestoreToken = token;
         mRestoreDataDir = new File(mDataDir, Long.toString(token));
-        return BackupConstants.TRANSPORT_OK;
+        return BackupTransport.TRANSPORT_OK;
     }
 
     public String nextRestorePackage() {
@@ -281,7 +281,7 @@
         ArrayList<DecodedFilename> blobs = contentsByKey(packageDir);
         if (blobs == null) {  // nextRestorePackage() ensures the dir exists, so this is an error
             Log.e(TAG, "No keys for package: " + packageDir);
-            return BackupConstants.TRANSPORT_ERROR;
+            return BackupTransport.TRANSPORT_ERROR;
         }
 
         // We expect at least some data if the directory exists in the first place
@@ -302,10 +302,10 @@
                     in.close();
                 }
             }
-            return BackupConstants.TRANSPORT_OK;
+            return BackupTransport.TRANSPORT_OK;
         } catch (IOException e) {
             Log.e(TAG, "Unable to read backup records", e);
-            return BackupConstants.TRANSPORT_ERROR;
+            return BackupTransport.TRANSPORT_ERROR;
         }
     }
 
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index ba419f9..dab3aff 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -20,6 +20,7 @@
 import android.util.Slog;
 
 import java.io.File;
+import java.io.IOException;
 
 /**
  * Native libraries helper.
@@ -141,4 +142,18 @@
 
         return deletedFiles;
     }
+
+    // We don't care about the other return values for now.
+    private static final int BITCODE_PRESENT = 1;
+
+    public static boolean hasRenderscriptBitcode(ApkHandle handle) throws IOException {
+        final int returnVal = hasRenderscriptBitcode(handle.apkHandle);
+        if (returnVal < 0) {
+            throw new IOException("Error scanning APK, code: " + returnVal);
+        }
+
+        return (returnVal == BITCODE_PRESENT);
+    }
+
+    private static native int hasRenderscriptBitcode(long apkHandle);
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index df96488..7dbde69 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -34,6 +34,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.TreeMap;
 
 /**
@@ -117,6 +118,24 @@
                     + " mIsSystemLanguage=" + mIsSystemLanguage
                     + "}";
         }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (o instanceof ImeSubtypeListItem) {
+                final ImeSubtypeListItem that = (ImeSubtypeListItem)o;
+                if (!Objects.equals(this.mImi, that.mImi)) {
+                    return false;
+                }
+                if (this.mSubtypeId != that.mSubtypeId) {
+                    return false;
+                }
+                return true;
+            }
+            return false;
+        }
     }
 
     private static class InputMethodAndSubtypeList {
@@ -276,7 +295,7 @@
         private final List<ImeSubtypeListItem> mImeSubtypeList;
         private final int[] mUsageHistoryOfSubtypeListItemIndex;
 
-        public DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) {
+        private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) {
             mImeSubtypeList = imeSubtypeListItems;
             mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()];
             final int N = mImeSubtypeList.size();
@@ -347,15 +366,53 @@
 
     @VisibleForTesting
     public static class ControllerImpl {
-        // TODO: Switch to DynamicRotationList for smarter rotation.
-        private final StaticRotationList mSwitchingAwareSubtypeList;
-        private final StaticRotationList mSwitchingUnawareSubtypeList;
+        private final DynamicRotationList mSwitchingAwareRotationList;
+        private final StaticRotationList mSwitchingUnawareRotationList;
 
-        public ControllerImpl(final List<ImeSubtypeListItem> sortedItems) {
-            mSwitchingAwareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems,
-                    true /* supportsSwitchingToNextInputMethod */));
-            mSwitchingUnawareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems,
-                    false /* supportsSwitchingToNextInputMethod */));
+        public static ControllerImpl createFrom(final ControllerImpl currentInstance,
+                final List<ImeSubtypeListItem> sortedEnabledItems) {
+            DynamicRotationList switchingAwareRotationList = null;
+            {
+                final List<ImeSubtypeListItem> switchingAwareImeSubtypes =
+                        filterImeSubtypeList(sortedEnabledItems,
+                                true /* supportsSwitchingToNextInputMethod */);
+                if (currentInstance != null &&
+                        currentInstance.mSwitchingAwareRotationList != null &&
+                        Objects.equals(currentInstance.mSwitchingAwareRotationList.mImeSubtypeList,
+                                switchingAwareImeSubtypes)) {
+                    // Can reuse the current instance.
+                    switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList;
+                }
+                if (switchingAwareRotationList == null) {
+                    switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes);
+                }
+            }
+
+            StaticRotationList switchingUnawareRotationList = null;
+            {
+                final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList(
+                        sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */);
+                if (currentInstance != null &&
+                        currentInstance.mSwitchingUnawareRotationList != null &&
+                        Objects.equals(
+                                currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList,
+                                switchingUnawareImeSubtypes)) {
+                    // Can reuse the current instance.
+                    switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList;
+                }
+                if (switchingUnawareRotationList == null) {
+                    switchingUnawareRotationList =
+                            new StaticRotationList(switchingUnawareImeSubtypes);
+                }
+            }
+
+            return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList);
+        }
+
+        private ControllerImpl(final DynamicRotationList switchingAwareRotationList,
+                final StaticRotationList switchingUnawareRotationList) {
+            mSwitchingAwareRotationList = switchingAwareRotationList;
+            mSwitchingUnawareRotationList = switchingUnawareRotationList;
         }
 
         public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi,
@@ -364,10 +421,10 @@
                 return null;
             }
             if (imi.supportsSwitchingToNextInputMethod()) {
-                return mSwitchingAwareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi,
+                return mSwitchingAwareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi,
                         subtype);
             } else {
-                return mSwitchingUnawareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi,
+                return mSwitchingUnawareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi,
                         subtype);
             }
         }
@@ -376,10 +433,9 @@
             if (imi == null) {
                 return;
             }
-            // TODO: Enable the following code when DynamicRotationList is enabled.
-            // if (imi.supportsSwitchingToNextInputMethod()) {
-            //     mSwitchingAwareSubtypeList.onUserAction(imi, subtype);
-            // }
+            if (imi.supportsSwitchingToNextInputMethod()) {
+                mSwitchingAwareRotationList.onUserAction(imi, subtype);
+            }
         }
 
         private static List<ImeSubtypeListItem> filterImeSubtypeList(
@@ -424,7 +480,8 @@
 
     public void resetCircularListLocked(Context context) {
         mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
-        mController = new ControllerImpl(mSubtypeList.getSortedInputMethodAndSubtypeList());
+        mController = ControllerImpl.createFrom(mController,
+                mSubtypeList.getSortedInputMethodAndSubtypeList());
     }
 
     public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi,
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index ed9f9bc..240d520 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2006,6 +2006,11 @@
         }
     }
 
+    @Override
+    public void commitCurrentHistoryBatchLocked() {
+        mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+    }
+
     void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
         if (!mHaveBatteryLevel || !mRecordingHistory) {
             return;
@@ -2342,13 +2347,16 @@
             // Only care about partial wake locks, since full wake locks
             // will be canceled when the user puts the screen to sleep.
             aggregateLastWakeupUptimeLocked(uptime);
+            if (historyName == null) {
+                historyName = name;
+            }
             if (mRecordAllWakeLocks) {
-                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, name, uid, 0)) {
+                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
+                        uid, 0)) {
                     addHistoryEventLocked(elapsedRealtime, uptime,
-                            HistoryItem.EVENT_WAKE_LOCK_START, name, uid);
+                            HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
                 }
             }
-            historyName = historyName == null ? name : historyName;
             if (mWakeLockNesting == 0) {
                 mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
@@ -2358,7 +2366,8 @@
                 mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
                 mWakeLockImportant = !unimportantForLogging;
                 addHistoryRecordLocked(elapsedRealtime, uptime);
-            } else if (!mWakeLockImportant && !unimportantForLogging) {
+            } else if (!mWakeLockImportant && !unimportantForLogging
+                    && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
                 if (mHistoryLastWritten.wakelockTag != null) {
                     // We'll try to update the last tag.
                     mHistoryLastWritten.wakelockTag = null;
@@ -2386,9 +2395,13 @@
         if (type == WAKE_TYPE_PARTIAL) {
             mWakeLockNesting--;
             if (mRecordAllWakeLocks) {
-                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, name, uid, 0)) {
+                if (historyName == null) {
+                    historyName = name;
+                }
+                if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
+                        uid, 0)) {
                     addHistoryEventLocked(elapsedRealtime, uptime,
-                            HistoryItem.EVENT_WAKE_LOCK_FINISH, name, uid);
+                            HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
                 }
             }
             if (mWakeLockNesting == 0) {
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index a56fa36..d66ef83 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -169,6 +169,15 @@
         return false;
     }
 
+    public static boolean contains(long[] array, long value) {
+        for (long element : array) {
+            if (element == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public static long total(long[] array) {
         long total = 0;
         for (long value : array) {
@@ -229,6 +238,14 @@
         return array;
     }
 
+    /**
+     * Appends a new value to a copy of the array and returns the copy.  If
+     * the value is already present, the original array is returned
+     * @param cur The original array, or null to represent an empty array.
+     * @param val The value to add.
+     * @return A new array that contains all of the values of the original array
+     * with the new value added, or the original array.
+     */
     public static int[] appendInt(int[] cur, int val) {
         if (cur == null) {
             return new int[] { val };
@@ -264,4 +281,48 @@
         }
         return cur;
     }
+
+    /**
+     * Appends a new value to a copy of the array and returns the copy.  If
+     * the value is already present, the original array is returned
+     * @param cur The original array, or null to represent an empty array.
+     * @param val The value to add.
+     * @return A new array that contains all of the values of the original array
+     * with the new value added, or the original array.
+     */
+    public static long[] appendLong(long[] cur, long val) {
+        if (cur == null) {
+            return new long[] { val };
+        }
+        final int N = cur.length;
+        for (int i = 0; i < N; i++) {
+            if (cur[i] == val) {
+                return cur;
+            }
+        }
+        long[] ret = new long[N + 1];
+        System.arraycopy(cur, 0, ret, 0, N);
+        ret[N] = val;
+        return ret;
+    }
+
+    public static long[] removeLong(long[] cur, long val) {
+        if (cur == null) {
+            return null;
+        }
+        final int N = cur.length;
+        for (int i = 0; i < N; i++) {
+            if (cur[i] == val) {
+                long[] ret = new long[N - 1];
+                if (i > 0) {
+                    System.arraycopy(cur, 0, ret, 0, i);
+                }
+                if (i < (N - 1)) {
+                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
+                }
+                return ret;
+            }
+        }
+        return cur;
+    }
 }
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 81e67d8..af966b1 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -57,9 +57,9 @@
     public static final int BASE_DNS_PINGER                                         = 0x00050000;
     public static final int BASE_NSD_MANAGER                                        = 0x00060000;
     public static final int BASE_NETWORK_STATE_TRACKER                              = 0x00070000;
-    public static final int BASE_CONNECTIVITY_SERVICE                               = 0x00080000;
+    public static final int BASE_CONNECTIVITY_MANAGER                               = 0x00080000;
     public static final int BASE_NETWORK_AGENT                                      = 0x00081000;
     public static final int BASE_NETWORK_MONITOR                                    = 0x00082000;
-    public static final int BASE_CONNECTIVITY_MANAGER                               = 0x00083000;
+    public static final int BASE_NETWORK_FACTORY                                    = 0x00083000;
     //TODO: define all used protocols
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f446c3a..a1cd7f7 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -57,7 +57,6 @@
 	android_view_KeyEvent.cpp \
 	android_view_KeyCharacterMap.cpp \
 	android_view_GraphicBuffer.cpp \
-	android_view_GLRenderer.cpp \
 	android_view_GLES20Canvas.cpp \
 	android_view_HardwareLayer.cpp \
 	android_view_ThreadedRenderer.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e069876..e0c5e96 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -130,7 +130,6 @@
 extern int register_android_view_RenderNodeAnimator(JNIEnv* env);
 extern int register_android_view_GraphicBuffer(JNIEnv* env);
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
-extern int register_android_view_GLRenderer(JNIEnv* env);
 extern int register_android_view_HardwareLayer(JNIEnv* env);
 extern int register_android_view_ThreadedRenderer(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
@@ -1214,7 +1213,6 @@
     REG_JNI(register_android_view_RenderNodeAnimator),
     REG_JNI(register_android_view_GraphicBuffer),
     REG_JNI(register_android_view_GLES20Canvas),
-    REG_JNI(register_android_view_GLRenderer),
     REG_JNI(register_android_view_HardwareLayer),
     REG_JNI(register_android_view_ThreadedRenderer),
     REG_JNI(register_android_view_Surface),
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 3bab8a2..dd6b36f 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -23,6 +23,9 @@
 #include "GraphicsJNI.h"
 #include <ScopedPrimitiveArray.h>
 #include <ScopedUtfChars.h>
+#include <android_runtime/android_util_AssetManager.h>
+#include <androidfw/AssetManager.h>
+#include "Utils.h"
 
 #ifdef USE_MINIKIN
 #include <minikin/FontFamily.h>
@@ -51,19 +54,60 @@
 #endif
 }
 
+#ifdef USE_MINIKIN
+static jboolean addSkTypeface(FontFamily* family, SkTypeface* face) {
+    MinikinFont* minikinFont = new MinikinFontSkia(face);
+    bool result = family->addFont(minikinFont);
+    minikinFont->Unref();
+    return result;
+}
+#endif
+
 static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path) {
 #ifdef USE_MINIKIN
     NPE_CHECK_RETURN_ZERO(env, path);
     ScopedUtfChars str(env, path);
-    ALOGD("addFont %s", str.c_str());
     SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
     if (face == NULL) {
         ALOGE("addFont failed to create font %s", str.c_str());
         return false;
     }
-    MinikinFont* minikinFont = new MinikinFontSkia(face);
     FontFamily* fontFamily = (FontFamily*)familyPtr;
-    return fontFamily->addFont(minikinFont);
+    return addSkTypeface(fontFamily, face);
+#else
+    return false;
+#endif
+}
+
+static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
+        jobject jassetMgr, jstring jpath) {
+#ifdef USE_MINIKIN
+    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
+    NPE_CHECK_RETURN_ZERO(env, jpath);
+
+    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
+    if (NULL == mgr) {
+        return false;
+    }
+
+    ScopedUtfChars str(env, jpath);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (NULL == asset) {
+        return false;
+    }
+
+    SkStream* stream = new AssetStreamAdaptor(asset,
+                                              AssetStreamAdaptor::kYes_OwnAsset,
+                                              AssetStreamAdaptor::kYes_HasMemoryBase);
+    SkTypeface* face = SkTypeface::CreateFromStream(stream);
+    // Note: SkTypeface::CreateFromStream holds its own reference to the stream
+    stream->unref();
+    if (face == NULL) {
+        ALOGE("addFontFromAsset failed to create font %s", str.c_str());
+        return false;
+    }
+    FontFamily* fontFamily = (FontFamily*)familyPtr;
+    return addSkTypeface(fontFamily, face);
 #else
     return false;
 #endif
@@ -75,6 +119,8 @@
     { "nCreateFamily",            "(Ljava/lang/String;I)J", (void*)FontFamily_create },
     { "nUnrefFamily",             "(J)V", (void*)FontFamily_unref },
     { "nAddFont",                 "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
+    { "nAddFontFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
+                                           (void*)FontFamily_addFontFromAsset },
 };
 
 int register_android_graphics_FontFamily(JNIEnv* env)
diff --git a/core/jni/android/graphics/MinikinSkia.h b/core/jni/android/graphics/MinikinSkia.h
index 7a8954d..1cc2c51 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/core/jni/android/graphics/MinikinSkia.h
@@ -18,6 +18,7 @@
 
 class MinikinFontSkia : public MinikinFont {
 public:
+    // Note: this takes ownership of the reference (will unref on dtor)
     explicit MinikinFontSkia(SkTypeface *typeface);
 
     ~MinikinFontSkia();
diff --git a/core/jni/android/graphics/TypefaceImpl.cpp b/core/jni/android/graphics/TypefaceImpl.cpp
index 958cd85..ff52b07 100644
--- a/core/jni/android/graphics/TypefaceImpl.cpp
+++ b/core/jni/android/graphics/TypefaceImpl.cpp
@@ -171,7 +171,9 @@
 }
 
 void TypefaceImpl_unref(TypefaceImpl* face) {
-    face->fFontCollection->Unref();
+    if (face != NULL) {
+        face->fFontCollection->Unref();
+    }
     delete face;
 }
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 9141d44..ecdfeb2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -91,53 +91,9 @@
 } gRectClassInfo;
 
 // ----------------------------------------------------------------------------
-// Caching
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz,
-        jint mode) {
-    if (Caches::hasInstance()) {
-        Caches::getInstance().flush(static_cast<Caches::FlushMode>(mode));
-    }
-}
-
-static jboolean android_view_GLES20Canvas_initCaches(JNIEnv* env, jobject clazz) {
-    if (Caches::hasInstance()) {
-        return Caches::getInstance().init() ? JNI_TRUE : JNI_FALSE;
-    }
-    return JNI_FALSE;
-}
-
-static void android_view_GLES20Canvas_terminateCaches(JNIEnv* env, jobject clazz) {
-    if (Caches::hasInstance()) {
-        Caches::getInstance().terminate();
-    }
-}
-
-// ----------------------------------------------------------------------------
-// Caching
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
-        jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
-
-    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
-    jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
-    Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
-    env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
-}
-
-// ----------------------------------------------------------------------------
 // Constructors
 // ----------------------------------------------------------------------------
 
-static jlong android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
-    RENDERER_LOGD("Create OpenGLRenderer");
-    OpenGLRenderer* renderer = new OpenGLRenderer();
-    renderer->initProperties();
-    return reinterpret_cast<jlong>(renderer);
-}
-
 static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
         jlong rendererPtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
@@ -174,10 +130,6 @@
     renderer->finish();
 }
 
-static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
-    return Stencil::getStencilSize();
-}
-
 static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
         jobject clazz, jstring name, jstring value) {
     if (!Caches::hasInstance()) {
@@ -577,15 +529,6 @@
     }
 }
 
-static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jfloatArray rects, jint count, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    jfloat* storage = env->GetFloatArrayElements(rects, NULL);
-    SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
-    renderer->drawRects(storage, count, paint);
-    env->ReleaseFloatArrayElements(rects, storage, 0);
-}
-
 static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
@@ -924,39 +867,6 @@
     renderer->drawLayer(layer, x, y);
 }
 
-static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
-        jlong layerPtr, jlong bitmapPtr) {
-    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
-    return LayerRenderer::copyLayer(layer, bitmap);
-}
-
-static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong layerPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
-    renderer->pushLayerUpdate(layer);
-}
-
-static void android_view_GLES20Canvas_cancelLayerUpdate(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong layerPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
-    renderer->cancelLayerUpdate(layer);
-}
-
-static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    renderer->clearLayerUpdates();
-}
-
-static void android_view_GLES20Canvas_flushLayerUpdates(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    renderer->flushLayerUpdates();
-}
-
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -1001,14 +911,7 @@
     { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
 
 #ifdef USE_OPENGL_RENDERER
-    { "nFlushCaches",       "(I)V",            (void*) android_view_GLES20Canvas_flushCaches },
-    { "nInitCaches",        "()Z",             (void*) android_view_GLES20Canvas_initCaches },
-    { "nTerminateCaches",   "()V",             (void*) android_view_GLES20Canvas_terminateCaches },
 
-    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[JI)V",
-            (void*) android_view_GLES20Canvas_initAtlas },
-
-    { "nCreateRenderer",    "()J",             (void*) android_view_GLES20Canvas_createRenderer },
     { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
     { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
     { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
@@ -1017,9 +920,6 @@
     { "nSetProperty",           "(Ljava/lang/String;Ljava/lang/String;)V",
             (void*) android_view_GLES20Canvas_setProperty },
 
-
-    { "nGetStencilSize",    "()I",             (void*) android_view_GLES20Canvas_getStencilSize },
-
     { "nCallDrawGLFunction", "(JJ)I",          (void*) android_view_GLES20Canvas_callDrawGLFunction },
 
     { "nSave",              "(JI)I",           (void*) android_view_GLES20Canvas_save },
@@ -1059,7 +959,6 @@
     { "nDrawColor",         "(JII)V",          (void*) android_view_GLES20Canvas_drawColor },
     { "nDrawRect",          "(JFFFFJ)V",       (void*) android_view_GLES20Canvas_drawRect },
     { "nDrawRects",         "(JJJ)V",          (void*) android_view_GLES20Canvas_drawRegionAsRects },
-    { "nDrawRects",         "(J[FIJ)V",        (void*) android_view_GLES20Canvas_drawRects },
     { "nDrawRoundRect",     "(JFFFFFFJ)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
     { "nDrawCircle",        "(JFFFJ)V",        (void*) android_view_GLES20Canvas_drawCircle },
     { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_GLES20Canvas_drawCircleProps },
@@ -1099,11 +998,6 @@
     { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
 
     { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
-    { "nCopyLayer",              "(JJ)Z",      (void*) android_view_GLES20Canvas_copyLayer },
-    { "nClearLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_clearLayerUpdates },
-    { "nFlushLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_flushLayerUpdates },
-    { "nPushLayerUpdate",        "(JJ)V",      (void*) android_view_GLES20Canvas_pushLayerUpdate },
-    { "nCancelLayerUpdate",      "(JJ)V",      (void*) android_view_GLES20Canvas_cancelLayerUpdate },
 
     { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
     { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
deleted file mode 100644
index d0269a3..0000000
--- a/core/jni/android_view_GLRenderer.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "GLRenderer"
-
-#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include <android_runtime/AndroidRuntime.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <EGL/egl_cache.h>
-
-#include <utils/Timers.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-#include <Caches.h>
-#include <Extensions.h>
-#include <LayerRenderer.h>
-#include <RenderNode.h>
-
-#ifdef USE_OPENGL_RENDERER
-    EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
-#endif
-
-namespace android {
-
-/**
- * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
- *       devices. This means all the logic must be compiled only when the
- *       preprocessor variable USE_OPENGL_RENDERER is defined.
- */
-#ifdef USE_OPENGL_RENDERER
-
-// ----------------------------------------------------------------------------
-// Defines
-// ----------------------------------------------------------------------------
-
-// Debug
-#define DEBUG_RENDERER 0
-
-// Debug
-#if DEBUG_RENDERER
-    #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-    #define RENDERER_LOGD(...)
-#endif
-
-// ----------------------------------------------------------------------------
-// Surface and display management
-// ----------------------------------------------------------------------------
-
-static jboolean android_view_GLRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) {
-    EGLDisplay display = eglGetCurrentDisplay();
-    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-
-    eglGetError();
-    eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
-
-    EGLint error = eglGetError();
-    if (error != EGL_SUCCESS) {
-        RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
-    }
-
-    return error == EGL_SUCCESS;
-}
-
-static jboolean android_view_GLRenderer_isBackBufferPreserved(JNIEnv* env, jobject clazz) {
-    EGLDisplay display = eglGetCurrentDisplay();
-    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-    EGLint value;
-
-    eglGetError();
-    eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value);
-
-    EGLint error = eglGetError();
-    if (error != EGL_SUCCESS) {
-        RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error);
-    }
-
-    return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
-}
-
-// ----------------------------------------------------------------------------
-// Tracing and debugging
-// ----------------------------------------------------------------------------
-
-static bool android_view_GLRenderer_loadProperties(JNIEnv* env, jobject clazz) {
-    if (uirenderer::Caches::hasInstance()) {
-        return uirenderer::Caches::getInstance().initProperties();
-    }
-    return false;
-}
-
-static void android_view_GLRenderer_beginFrame(JNIEnv* env, jobject clazz,
-        jintArray size) {
-
-    EGLDisplay display = eglGetCurrentDisplay();
-    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-
-    if (size) {
-        EGLint value;
-        jint* storage = env->GetIntArrayElements(size, NULL);
-
-        eglQuerySurface(display, surface, EGL_WIDTH, &value);
-        storage[0] = value;
-
-        eglQuerySurface(display, surface, EGL_HEIGHT, &value);
-        storage[1] = value;
-
-        env->ReleaseIntArrayElements(size, storage, 0);
-    }
-
-    eglBeginFrame(display, surface);
-}
-
-static jlong android_view_GLRenderer_getSystemTime(JNIEnv* env, jobject clazz) {
-    if (uirenderer::Extensions::getInstance().hasNvSystemTime()) {
-        return eglGetSystemTimeNV();
-    }
-    return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static void android_view_GLRenderer_destroyLayer(JNIEnv* env, jobject clazz,
-        jlong layerPtr) {
-    using namespace android::uirenderer;
-    Layer* layer = reinterpret_cast<Layer*>(layerPtr);
-    LayerRenderer::destroyLayer(layer);
-}
-
-static void android_view_GLRenderer_prepareTree(JNIEnv* env, jobject clazz,
-        jlong renderNodePtr) {
-    using namespace android::uirenderer;
-    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    TreeInfo ignoredInfo;
-    renderNode->prepareTree(ignoredInfo);
-}
-
-static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
-        jlong functorPtr, jboolean hasContext) {
-    using namespace android::uirenderer;
-    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    DrawGlInfo::Mode mode = hasContext ? DrawGlInfo::kModeProcess : DrawGlInfo::kModeProcessNoContext;
-    (*functor)(mode, NULL);
-}
-
-#endif // USE_OPENGL_RENDERER
-
-// ----------------------------------------------------------------------------
-// Shaders
-// ----------------------------------------------------------------------------
-
-static void android_view_GLRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
-        jstring diskCachePath) {
-
-    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
-    egl_cache_t::get()->setCacheFilename(cacheArray);
-    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
-}
-
-// ----------------------------------------------------------------------------
-// JNI Glue
-// ----------------------------------------------------------------------------
-
-const char* const kClassPathName = "android/view/GLRenderer";
-
-static JNINativeMethod gMethods[] = {
-#ifdef USE_OPENGL_RENDERER
-    { "isBackBufferPreserved", "()Z",   (void*) android_view_GLRenderer_isBackBufferPreserved },
-    { "preserveBackBuffer",    "()Z",   (void*) android_view_GLRenderer_preserveBackBuffer },
-    { "loadProperties",        "()Z",   (void*) android_view_GLRenderer_loadProperties },
-
-    { "beginFrame",            "([I)V", (void*) android_view_GLRenderer_beginFrame },
-
-    { "getSystemTime",         "()J",   (void*) android_view_GLRenderer_getSystemTime },
-    { "nDestroyLayer",         "(J)V",  (void*) android_view_GLRenderer_destroyLayer },
-    { "nPrepareTree", "(J)V", (void*) android_view_GLRenderer_prepareTree },
-    { "nInvokeFunctor",        "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
-#endif
-
-    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
-            (void*) android_view_GLRenderer_setupShadersDiskCache },
-};
-
-int register_android_view_GLRenderer(JNIEnv* env) {
-    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 33a2705..879836d 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -43,21 +43,6 @@
 
 #ifdef USE_OPENGL_RENDERER
 
-static jlong android_view_HardwareLayer_createTextureLayer(JNIEnv* env, jobject clazz) {
-    Layer* layer = LayerRenderer::createTextureLayer();
-    if (!layer) return 0;
-
-    return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
-}
-
-static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject clazz,
-        jint width, jint height) {
-    Layer* layer = LayerRenderer::createRenderLayer(width, height);
-    if (!layer) return 0;
-
-    return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
-}
-
 static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz,
         jlong layerUpdaterPtr) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
@@ -140,8 +125,6 @@
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
 
-    { "nCreateTextureLayer",     "()J",        (void*) android_view_HardwareLayer_createTextureLayer },
-    { "nCreateRenderLayer",      "(II)J",      (void*) android_view_HardwareLayer_createRenderLayer },
     { "nOnTextureDestroyed",     "(J)V",       (void*) android_view_HardwareLayer_onTextureDestroyed },
 
     { "nPrepare",                "(JIIZ)Z",    (void*) android_view_HardwareLayer_prepare },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index e19ce36..d689864 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -116,6 +116,11 @@
     return reinterpret_cast<jlong>( animator );
 }
 
+static void setStartValue(JNIEnv* env, jobject clazz, jlong animatorPtr, jfloat startValue) {
+    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
+    animator->setStartValue(startValue);
+}
+
 static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong duration) {
     LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
     BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
@@ -157,6 +162,7 @@
     { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator },
     { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator },
     { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator },
+    { "nSetStartValue", "(JF)V", (void*) setStartValue },
     { "nSetDuration", "(JJ)V", (void*) setDuration },
     { "nGetDuration", "(J)J", (void*) getDuration },
     { "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 1397131..a550649 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -22,6 +22,10 @@
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <EGL/egl_cache.h>
+
 #include <utils/StrongPointer.h>
 #include <android_runtime/android_view_Surface.h>
 #include <system/window.h>
@@ -329,6 +333,18 @@
 #endif
 
 // ----------------------------------------------------------------------------
+// Shaders
+// ----------------------------------------------------------------------------
+
+static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
+        jstring diskCachePath) {
+
+    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
+    egl_cache_t::get()->setCacheFilename(cacheArray);
+    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
+}
+
+// ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
 
@@ -361,6 +377,8 @@
     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
 #endif
+    { "setupShadersDiskCache", "(Ljava/lang/String;)V",
+                (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
 };
 
 int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 230658f..e55e4ea 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -46,6 +46,9 @@
 #define LIB_SUFFIX ".so"
 #define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1)
 
+#define RS_BITCODE_SUFFIX ".bc"
+#define RS_BITCODE_SUFFIX_LEN (sizeof(RS_BITCODE_SUFFIX) -1)
+
 #define GDBSERVER "gdbserver"
 #define GDBSERVER_LEN (sizeof(GDBSERVER) - 1)
 
@@ -486,6 +489,42 @@
     return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch);
 }
 
+enum bitcode_scan_result_t {
+  APK_SCAN_ERROR = -1,
+  NO_BITCODE_PRESENT = 0,
+  BITCODE_PRESENT = 1,
+};
+
+static jint
+com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode(JNIEnv *env, jclass clazz,
+        jlong apkHandle) {
+    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+    void* cookie = NULL;
+    if (!zipFile->startIteration(&cookie)) {
+        return APK_SCAN_ERROR;
+    }
+
+    char fileName[PATH_MAX];
+    ZipEntryRO next = NULL;
+    while ((next = zipFile->nextEntry(cookie)) != NULL) {
+        if (zipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
+            continue;
+        }
+
+        const size_t fileNameLen = strlen(fileName);
+        const char* lastSlash = strrchr(fileName, '/');
+        const char* baseName = (lastSlash == NULL) ? fileName : fileName + 1;
+        if (!strncmp(fileName + fileNameLen - RS_BITCODE_SUFFIX_LEN, RS_BITCODE_SUFFIX,
+                     RS_BITCODE_SUFFIX_LEN) && isFilenameSafe(baseName)) {
+            zipFile->endIteration(cookie);
+            return BITCODE_PRESENT;
+        }
+    }
+
+    zipFile->endIteration(cookie);
+    return NO_BITCODE_PRESENT;
+}
+
 static jlong
 com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath)
 {
@@ -517,6 +556,8 @@
     {"nativeFindSupportedAbi",
             "(J[Ljava/lang/String;)I",
             (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
+    {"hasRenderscriptBitcode", "(J)I",
+            (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode},
 };
 
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bb6a1cb..fe703b2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2076,7 +2076,7 @@
         android:description="@string/permdesc_bindRemoteDisplay"
         android:protectionLevel="signature" />
 
-    <!-- Must be required by a {@link android.tv.TvInputService}
+    <!-- Must be required by a {@link android.media.tv.TvInputService}
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_TV_INPUT"
         android:label="@string/permlab_bindTvInput"
diff --git a/core/res/res/anim/voice_activity_open_enter.xml b/core/res/res/anim/voice_activity_open_enter.xml
index 57fba2a..ce7a4f9 100644
--- a/core/res/res/anim/voice_activity_open_enter.xml
+++ b/core/res/res/anim/voice_activity_open_enter.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/fade_in.xml
 **
 ** Copyright 2007, The Android Open Source Project
 **
diff --git a/core/res/res/anim/voice_layer_enter.xml b/core/res/res/anim/voice_layer_enter.xml
index 57fba2a..ce7a4f9 100644
--- a/core/res/res/anim/voice_layer_enter.xml
+++ b/core/res/res/anim/voice_layer_enter.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/fade_in.xml
 **
 ** Copyright 2007, The Android Open Source Project
 **
diff --git a/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index ba5bd01..0000000
--- a/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/work_icon.png b/core/res/res/drawable-hdpi/work_icon.png
index e90866b..be8a36e 100644
--- a/core/res/res/drawable-hdpi/work_icon.png
+++ b/core/res/res/drawable-hdpi/work_icon.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index 4e2612d..0000000
--- a/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index e6ca1ea..0000000
--- a/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index d6018dd..0000000
--- a/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_lock_bugreport.xml b/core/res/res/drawable/ic_lock_bugreport.xml
index a3f82ce..b93a09a 100644
--- a/core/res/res/drawable/ic_lock_bugreport.xml
+++ b/core/res/res/drawable/ic_lock_bugreport.xml
@@ -1,19 +1,28 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+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
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
 
-          http://www.apache.org/licenses/LICENSE-2.0
+         http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
 -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <size
+        android:width="32dp"
+        android:height="32dp"/>
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_lock_bugreport_alpha"
-    android:tint="?attr/colorControlNormal" />
+    <viewport
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"/>
+
+    <path
+        android:fill="?attr/colorControlNormal"
+        android:pathData="M20.0,8.0l-2.8,0.0c-0.5,-0.8 -1.1,-1.5 -1.8,-2.0L17.0,4.4L15.6,3.0l-2.2,2.2C13.0,5.1 12.5,5.0 12.0,5.0s-1.0,0.1 -1.4,0.2L8.4,3.0L7.0,4.4L8.6,6.0C7.9,6.5 7.3,7.2 6.8,8.0L4.0,8.0l0.0,2.0l2.1,0.0C6.0,10.3 6.0,10.7 6.0,11.0l0.0,1.0L4.0,12.0l0.0,2.0l2.0,0.0l0.0,1.0c0.0,0.3 0.0,0.7 0.1,1.0L4.0,16.0l0.0,2.0l2.8,0.0c1.0,1.8 3.0,3.0 5.2,3.0s4.2,-1.2 5.2,-3.0L20.0,18.0l0.0,-2.0l-2.1,0.0c0.1,-0.3 0.1,-0.7 0.1,-1.0l0.0,-1.0l2.0,0.0l0.0,-2.0l-2.0,0.0l0.0,-1.0c0.0,-0.3 0.0,-0.7 -0.1,-1.0L20.0,10.0L20.0,8.0zM14.0,16.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,16.0zM14.0,12.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,12.0z"/>
+</vector>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index f3b8495..dbe2d7f 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -68,7 +68,7 @@
   </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
-    <string name="ClipMmi" msgid="6952821216480289285">"លេខ​សម្គាល់​អ្នក​ហៅ​​ចូល"</string>
+    <string name="ClipMmi" msgid="6952821216480289285">"លេខ​សម្គាល់​អ្នក​ហៅ​​ចូល​"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"លេខ​សម្គាល់​អ្នក​ហៅ​ចេញ"</string>
     <string name="CfMmi" msgid="5123218989141573515">"បញ្ជូន​ការ​ហៅ​បន្ត"</string>
     <string name="CwMmi" msgid="9129678056795016867">"រង់ចាំ​ការ​ហៅ"</string>
@@ -125,7 +125,7 @@
     <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិន​បាន​បញ្ជូន​បន្ត"</string>
     <string name="fcComplete" msgid="3118848230966886575">"កូដ​លក្ខណៈ​ពេញលេញ។"</string>
     <string name="fcError" msgid="3327560126588500777">"បញ្ហា​ការ​តភ្ជាប់​ ឬ​កូដ​លក្ខណៈ​​​មិន​ត្រឹមត្រូវ​។"</string>
-    <string name="httpErrorOk" msgid="1191919378083472204">"យល់​ព្រម"</string>
+    <string name="httpErrorOk" msgid="1191919378083472204">"យល់​ព្រម​"</string>
     <string name="httpError" msgid="7956392511146698522">"មាន​កំហុស​បណ្ដាញ។"</string>
     <string name="httpErrorLookup" msgid="4711687456111963163">"រក​មិន​ឃើញ URL ។"</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"គ្រោងការណ៍​ផ្ទៀងផ្ទាត់​តំបន់បណ្ដាញ​មិន​ត្រូវ​បាន​គាំទ្រ។"</string>
@@ -183,7 +183,7 @@
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"បើក​សំឡេង"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"បាន​បើក​របៀប​ពេល​ជិះ​យន្ត​ហោះ"</string>
-    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ"</string>
+    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ​"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ការ​កំណត់"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
@@ -195,7 +195,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"សារ​របស់​អ្នក"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"អាន និង​សរសេរ​សារ SMS, អ៊ីមែល និង​សារ​ផ្សេងៗ​ទៀត​របស់​អ្នក។"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"ព័ត៌មាន​ផ្ទាល់ខ្លួន​របស់​អ្នក"</string>
-    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​អ្នក​ ដែល​បា​ន​រក្សាទុក​ក្នុង​កាត​ទំនាក់ទំនង​របស់​អ្នក។"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​អ្នក​ ដែល​បា​ន​រក្សាទុក​ក្នុង​កាត​ទំនាក់ទំនង​របស់​អ្នក។​"</string>
     <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ព័ត៌មាន​សង្គម​របស់​អ្នក"</string>
     <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​ទំនាក់ទំនង និង​ការ​ភ្ជាប់​សង្គម​របស់​អ្នក។"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"ទីតាំង​របស់​អ្នក"</string>
@@ -384,7 +384,7 @@
     <string name="permdesc_readInputState" msgid="8387754901688728043">"ឲ្យ​កម្មវិធី​មើល​គ្រាប់​ចុច​ដែល​អ្នក​ចុច​ពេល​មាន​អន្តរកម្ម​ជា​មួយ​កម្មវិធី​ផ្សេង (ដូចជា បញ្ចូល​ពាក្យ​សម្ងាត់)។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"ចង​ទៅ​វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​វិធី​សាស្ត្រ​បញ្ចូល។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចង​សេវា​កម្ម​ភាព​មធ្យោបាយ​ងាយស្រួល"</string>
+    <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចង​សេវា​កម្ម​ភាព​មធ្យោបាយ​ងាយស្រួល​"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ឲ្យ​​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ភាព​ងាយស្រួល។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindPrintService" msgid="8462815179572748761">"ចង​សេវាកម្ម​​បោះពុម្ព"</string>
     <string name="permdesc_bindPrintService" msgid="7960067623209111135">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -402,7 +402,7 @@
     <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​​របស់​សេវាកម្ម​អន្តរកម្ម​សំឡេង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់​ទៅ​ការ​បង្ហាញ​ពី​ចម្ងាយ"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​ការ​បង្ហាញ​ពី​ចម្ងាយ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក"</string>
+    <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក​"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ភ្ជាប់​ទៅ​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​ច្រក"</string>
     <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ក្រុមហ៊ុន​ផ្ដល់​​ច្រក​ដែល​បាន​ចុះ​ឈ្មោះ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -410,7 +410,7 @@
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យ​ម្ចាស់​ផ្ញើ​គោលបំណង​​ទៅ​អ្នក​គ្រប់គ្រង​ឧបករណ៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់​ទៅ​ការ​បញ្ចូល​ទូរទស្សន៍"</string>
     <string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុចប្រទាក់​កម្រិត​ខ្ពស់​នៃ​ការ​បញ្ចូល​ទូរទស្សន៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​​​ឧបករណ៍"</string>
+    <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​​​ឧបករណ៍​​"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាត​​​ឲ្យ​ម្ចាស់​​​បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​ឧបករណ៍​សកម្ម​ចេញ​។ មិន​គួរ​ប្រើ​សម្រាប់​កម្មវិធី​​ធម្មតា​ទេ​។"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរ​ទិស​អេក្រង់"</string>
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"ឲ្យ​កម្មវិធី​ប្ដូរ​ការ​បង្វិល​អេក្រង់​នៅ​ពេល​ណា​មួយ។ មិន​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -422,9 +422,9 @@
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"ឲ្យ​កម្មវិធី​ស្នើ​​សញ្ញា​ដែល​បាន​ផ្ដល់​ត្រូវ​ផ្ញើ​ទៅ​ដំណើរការ​ស្ថិតស្ថេរ​​ទាំង​អស់។"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ធ្វើ​ឲ្យ​កម្មវិធី​ដំណើរការ​ជា​និច្ច"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ឲ្យ​កម្មវិធី​ធ្វើជា​ផ្នែក​​ស្ថិតស្ថេរ​ដោយ​ខ្លួន​ឯង​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កំណត់​អង្គ​ចងចាំ​ដែល​អាច​ប្រើ​បាន​ចំពោះ​កម្មវិធី​ផ្សេងៗ​ ដោយ​ធ្វើឲ្យ​កុំព្យូទ័រ​បន្ទះ​យឺត។"</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យ​កម្មវិធី ធ្វើជា​ផ្នែក​អចិន្ត្រៃយ៍​នៃ​ខ្លួន​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កម្រិត​អង្គ​ចងចាំ​អាច​ប្រើ​បាន​ ដើម្បី​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ធ្វើ​ឲ្យ​ទូរស័ព្ទ​របស់​អ្នក​យឺត។"</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យ​កម្មវិធី ធ្វើជា​ផ្នែក​អចិន្ត្រៃយ៍​នៃ​ខ្លួន​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កម្រិត​អង្គ​ចងចាំ​អាច​ប្រើ​បាន​ ដើម្បី​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ធ្វើ​ឲ្យ​ទូរស័ព្ទ​របស់​អ្នក​យឺត។​"</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"លុប​កម្មវិធី"</string>
-    <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យ​កម្មវិធី​លុប​កញ្ចប់ Android ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប​កម្មវិធី​សំខាន់​ៗ។"</string>
+    <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យ​កម្មវិធី​លុប​កញ្ចប់ Android ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប​កម្មវិធី​សំខាន់​ៗ។ ​"</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"លុប​ទិន្នន័យ​របស់​​កម្មវិធី​ផ្សេង"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"ឲ្យ​កម្មវិធី​សម្អាត​ទិន្នន័យ​អ្នក​ប្រើ។"</string>
     <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"លុប​ឃ្លាំង​សម្ងាត់​កម្មវិធី​ផ្សេងៗ"</string>
@@ -475,7 +475,7 @@
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​កុំព្យូទ័រ​បន្ទះ រួមមាន​ប្រេកង់​​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​ទាក់ទង​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់ទំនង​ជាក់លាក់។ សិទ្ធិ​​នេះ​អនុញ្ញាត​ឲ្យ​​​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង​របស់​អ្នក។"</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ប្រេកង់​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​បាន​ទាក់ទង​​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់​ទំនាក់​ជាក់លាក់។ សិទ្ធិ​នេះ​ឲ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"អាន​​កំណត់​ហេតុ​​​ហៅ"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យ​កម្មវិធី​អាន​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។"</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យ​កម្មវិធី​អាន​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។​"</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"ឲ្យ​កម្មវិធី​អាន​​​បញ្ជី​ហៅ​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នកដឹង។"</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"សរសេរ​បញ្ជី​ហៅ"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ឲ្យ​កម្មវិធី​កែ​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។​កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប ឬ​កែ​បញ្ជី​ហៅ​របស់​អ្នក។"</string>
@@ -609,7 +609,7 @@
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ឲ្យ​កម្មវិធី​កំណត់​ជំនួយ​ទំហំ​ផ្ទាំង​រូបភាព​ប្រព័ន្ធ។"</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"កំណត់​ប្រព័ន្ធ​ទៅ​លំនាំដើម​រោងចក្រ​ឡើងវិញ"</string>
     <string name="permdesc_masterClear" msgid="3665380492633910226">"ឲ្យ​កម្មវិធី​កំណត់​ប្រព័ន្ធ​​ដូច​ការ​កំណត់​ចេញ​ពី​រោងចក្រ​ឡើងវិញ​ពេញលេញ ដោយ​លុប​ទិន្នន័យ ការ​កំណត់​រចនាសម្ព័ន្ធ និង​កម្មវិធី​បាន​ដំឡើង។"</string>
-    <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់​​ម៉ោង"</string>
+    <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់​​ម៉ោង​"</string>
     <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"ឲ្យ​កម្មវិធី​ប្ដូរ​ម៉ោង​កុំព្យូទ័រ​បន្ទះ។"</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"ឲ្យ​កម្មវិធី​ប្ដូរ​ម៉ោង​ទូរស័ព្ទ។"</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"កំណត់​តំបន់​ពេលវេលា"</string>
@@ -775,7 +775,7 @@
   <string-array name="organizationTypes">
     <item msgid="7546335612189115615">"កន្លែង​ធ្វើការ"</item>
     <item msgid="4378074129049520373">"ផ្សេងៗ"</item>
-    <item msgid="3455047468583965104">"តាម​តម្រូវ​ការ"</item>
+    <item msgid="3455047468583965104">"តាម​តម្រូវ​ការ​"</item>
   </string-array>
   <string-array name="imProtocols">
     <item msgid="8595261363518459565">"AIM"</item>
@@ -791,7 +791,7 @@
     <string name="phoneTypeHome" msgid="2570923463033985887">"ផ្ទះ"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"​ចល័ត"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"កន្លែង​ធ្វើការ"</string>
-    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារ​កន្លែង​ធ្វើការ"</string>
+    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារ​កន្លែង​ធ្វើការ​"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"ទូរសារ​ផ្ទះ"</string>
     <string name="phoneTypePager" msgid="7582359955394921732">"ភេយ័រ"</string>
     <string name="phoneTypeOther" msgid="1544425847868765990">"ផ្សេងៗ"</string>
@@ -916,7 +916,7 @@
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"ព្យាយាម​លំនាំ​ច្រើន​ពេក"</string>
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"ដើម្បី​ដោះ​សោ ចូល​គណនី Google របស់​អ្នក។"</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ឈ្មោះ​អ្នក​ប្រើ (អ៊ីមែល​)"</string>
-    <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់"</string>
+    <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់​"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ចូល"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ភ្លេច​ឈ្មោះ​អ្នក​ប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
@@ -961,7 +961,7 @@
     <string name="factorytest_failed" msgid="5410270329114212041">"បាន​បរាជ័យ​ក្នុង​ការ​សាកល្បង​រោងចក្រ"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"សកម្មភាព FACTORY_TEST ត្រូវ​បាន​គាំទ្រ​សម្រាប់​តែ​កញ្ចប់​បាន​ដំឡើង​ក្នុង /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"រក​មិន​ឃើញ​កញ្ចប់​ដែល​ផ្ដល់​សកម្មភាព FACTORY_TEST ។"</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់​ផ្ដើម​ឡើង​វិញ"</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់​ផ្ដើម​ឡើង​វិញ​"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"ទំព័រ​មាន​ចំណងជើង \"<xliff:g id="TITLE">%s</xliff:g>\" សរសេរ៖"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"បញ្ជាក់​ការ​រុករក"</string>
@@ -1019,7 +1019,7 @@
     <string name="prepend_shortcut_label" msgid="2572214461676015642">"ម៉ឺនុយ +"</string>
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"ដកឃ្លា"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
-    <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប"</string>
+    <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប​"</string>
     <string name="search_go" msgid="8298016669822141719">"ស្វែងរក"</string>
     <string name="searchview_description_search" msgid="6749826639098512120">"ស្វែងរក"</string>
     <string name="searchview_description_query" msgid="5911778593125355124">"ស្វែងរក​សំណួរ"</string>
@@ -1103,18 +1103,18 @@
     <string name="preposition_for_date" msgid="9093949757757445117">"នៅ <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="preposition_for_time" msgid="5506831244263083793">"នៅ​ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="preposition_for_year" msgid="5040395640711867177">"ក្នុង​ឆ្នាំ <xliff:g id="YEAR">%s</xliff:g>"</string>
-    <string name="day" msgid="8144195776058119424">"ថ្ងៃ"</string>
+    <string name="day" msgid="8144195776058119424">"ថ្ងៃ​"</string>
     <string name="days" msgid="4774547661021344602">"​ថ្ងៃ"</string>
     <string name="hour" msgid="2126771916426189481">"ម៉ោង"</string>
     <string name="hours" msgid="894424005266852993">"ម៉ោង"</string>
-    <string name="minute" msgid="9148878657703769868">"នាទី"</string>
+    <string name="minute" msgid="9148878657703769868">"នាទី​"</string>
     <string name="minutes" msgid="5646001005827034509">"នាទី"</string>
-    <string name="second" msgid="3184235808021478">"វិនាទី"</string>
+    <string name="second" msgid="3184235808021478">"វិនាទី​"</string>
     <string name="seconds" msgid="3161515347216589235">"វិនាទី"</string>
-    <string name="week" msgid="5617961537173061583">"សប្ដាហ៍"</string>
-    <string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍"</string>
-    <string name="year" msgid="4001118221013892076">"ឆ្នាំ"</string>
-    <string name="years" msgid="6881577717993213522">"ឆ្នាំ"</string>
+    <string name="week" msgid="5617961537173061583">"សប្ដាហ៍​"</string>
+    <string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍​"</string>
+    <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>
@@ -1130,12 +1130,12 @@
     <string name="VideoView_error_title" msgid="3534509135438353077">"បញ្ហា​វីដេអូ"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"វីដេអូ​នេះ​មិន​ត្រឹមត្រូវ​សម្រាប់​​ចរន្ត​ចូល​ឧបករណ៍​នេះ។"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"មិន​អាច​ចាក់​វីដេអូ​នេះ។"</string>
-    <string name="VideoView_error_button" msgid="2822238215100679592">"យល់​ព្រម"</string>
+    <string name="VideoView_error_button" msgid="2822238215100679592">"យល់​ព្រម​"</string>
     <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="noon" msgid="7245353528818587908">"រសៀល"</string>
     <string name="Noon" msgid="3342127745230013127">"រសៀល"</string>
     <string name="midnight" msgid="7166259508850457595">"កណ្ដាលអធ្រាត្រ"</string>
-    <string name="Midnight" msgid="5630806906897892201">"កណ្ដាល​អធ្រាត្រ"</string>
+    <string name="Midnight" msgid="5630806906897892201">"កណ្ដាល​អធ្រាត្រ​"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
     <string name="selectAll" msgid="6876518925844129331">"ជ្រើស​ទាំងអស់"</string>
@@ -1152,13 +1152,13 @@
     <string name="inputMethod" msgid="1653630062304567879">"វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"សកម្មភាព​អត្ថបទ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"អស់​ទំហំ​ផ្ទុក"</string>
-    <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ"</string>
+    <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ​"</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
     <string name="app_running_notification_text" msgid="4653586947747330058">"ប៉ះ​ ដើម្បី​មើល​ព័ត៌មាន​បន្ថែម ឬ​បញ្ឈប់​កម្មវិធី។"</string>
-    <string name="ok" msgid="5970060430562524910">"យល់​ព្រម"</string>
-    <string name="cancel" msgid="6442560571259935130">"បោះ​បង់"</string>
-    <string name="yes" msgid="5362982303337969312">"យល់​ព្រម"</string>
-    <string name="no" msgid="5141531044935541497">"បោះ​បង់"</string>
+    <string name="ok" msgid="5970060430562524910">"យល់​ព្រម​"</string>
+    <string name="cancel" msgid="6442560571259935130">"បោះ​បង់​"</string>
+    <string name="yes" msgid="5362982303337969312">"យល់​ព្រម​"</string>
+    <string name="no" msgid="5141531044935541497">"បោះ​បង់​"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"ប្រយ័ត្ន"</string>
     <string name="loading" msgid="7933681260296021180">"កំពុង​ផ្ទុក..."</string>
     <string name="capital_on" msgid="1544682755514494298">"បើក"</string>
@@ -1167,7 +1167,7 @@
     <string name="whichHomeApplication" msgid="4616420172727326782">"ជ្រើស​កម្មវិធី​ដើម"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"ប្រើ​តាម​លំនាំដើម​សម្រាប់​សកម្មភាព​នេះ។"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាត​លំនាំដើម​ក្នុង​ការកំណត់​ប្រព័ន្ធ &gt; កម្មវិធី &gt; ទាញ​យក។"</string>
-    <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព"</string>
+    <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព​​"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើស​កម្មវិធី​សម្រាប់​ឧបករណ៍​យូអេសប៊ី"</string>
     <string name="noApplications" msgid="2991814273936504689">"គ្មាន​កម្មវិធី​អាច​អនុវត្ត​សកម្មភាព​នេះ។"</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
@@ -1178,7 +1178,7 @@
     <string name="anr_activity_process" msgid="5776209883299089767">"សកម្មភាព <xliff:g id="ACTIVITY">%1$s</xliff:g> មិន​ឆ្លើយតប។\n\nតើ​អ្នក​ចង់​បិទ​វា?"</string>
     <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> មិន​ឆ្លើយតប។ តើ​អ្នក​ចង់​បិទ​វា?"</string>
     <string name="anr_process" msgid="6513209874880517125">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> មិន​ឆ្លើយតប។ \n\nតើ​អ្នក​ចង់​បិទ​វា​ឬ?"</string>
-    <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម"</string>
+    <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម​"</string>
     <string name="report" msgid="4060218260984795706">"រាយការណ៍"</string>
     <string name="wait" msgid="7147118217226317732">"រង់ចាំ"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"ទំព័រ​ក្លាយ​ជា​មិន​ឆ្លើយតប។\n\nតើ​អ្នក​​ចង់​បិទ​វា?"</string>
@@ -1260,19 +1260,19 @@
     <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"នេះ​អាច​កាត់​លុយ"</font>" លើ​គណនី​ចល័ត​របស់​អ្នក។"</string>
     <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"វា​នឹង​គិត​ថ្លៃ​សេវាកម្ម​លើ​គណនី​ចល័ត​របស់​អ្នក។"</font></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ផ្ញើ"</string>
-    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះ​បង់"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះ​បង់​"</string>
     <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ចងចាំ​ជម្រើស​របស់​ខ្ញុំ"</string>
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"អ្នក​អាច​ប្ដូរ​វា​ពេល​ក្រោយ​ក្នុង​ការ​កំណត់ &gt; កម្មវិធី"</string>
     <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">"បាន​ដក​ស៊ីម​កាត​ចេញ"</string>
-    <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញ​ចល័ត​នឹង​ប្រើ​លែង​បាន​រហូត​ដល់​អ្នក​ចាប់ផ្ដើម​ជា​មួយ​ស៊ីម​កាត​ដែល​បា​បញ្ចូល​ត្រឹមត្រូវ។"</string>
+    <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញ​ចល័ត​នឹង​ប្រើ​លែង​បាន​រហូត​ដល់​អ្នក​ចាប់ផ្ដើម​ជា​មួយ​ស៊ីម​កាត​ដែល​បា​បញ្ចូល​ត្រឹមត្រូវ។​"</string>
     <string name="sim_done_button" msgid="827949989369963775">"រួចរាល់"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"បាន​បន្ថែម​ស៊ីម​កាត"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"ចាប់ផ្ដើម​ឧបករណ៍​របស់​អ្នក​ឡើង​វិញ ដើម្បី​ចូល​ដំណើរការ​បណ្ដាញ​ចល័ត។"</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>
+    <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់​ម៉ោង​"</string>
+    <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់​កាល​បរិច្ឆេទ​"</string>
     <string name="date_time_set" msgid="5777075614321087758">"កំណត់"</string>
     <string name="date_time_done" msgid="2507683751759308828">"រួចរាល់"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ថ្មី៖ "</font></string>
@@ -1350,7 +1350,7 @@
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"ឲ្យ​កម្មវិធី​ដក​សេវាកម្ម​នៃ​កម្មវិធី​ផ្ទុក​​លំនាំដើម ដើម្បី​ចម្លង​មាតិកា។​ មិន​សម្រាប់​ប្រើ​ដោយ​កម្មវិធី​លំនាំដើម។"</string>
     <string name="permlab_route_media_output" msgid="1642024455750414694">"នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ"</string>
     <string name="permdesc_route_media_output" msgid="4932818749547244346">"ឲ្យ​កម្មវិធី​នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ​ទៅ​ឧបករណ៍​​ខាង​ក្រៅ​ផ្សេង។"</string>
-    <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូល​ដំណើរការ​ឧបករណ៍​ផ្ទុក​សុវត្ថិភាព"</string>
+    <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូល​ដំណើរការ​ឧបករណ៍​ផ្ទុក​សុវត្ថិភាព​"</string>
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ឲ្យ​កម្មវិធី​ចូល​​ការ​ផ្ទុក​មាន​សុវត្ថិភាព keguard ។"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ពិនិត្យ​ការ​បង្ហាញ និង​លាក់​ការ​ការពារ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ឲ្យ​កម្មវិធី​គ្រប់គ្រង keguard ។"</string>
@@ -1365,7 +1365,7 @@
     <string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string>
     <string name="ime_action_search" msgid="658110271822807811">"ស្វែងរក"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"ផ្ញើ"</string>
-    <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់"</string>
+    <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់​"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"រួចរាល់"</string>
     <string name="ime_action_previous" msgid="1443550039250105948">"មុន"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"អនុវត្ត"</string>
@@ -1374,7 +1374,7 @@
     <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"កម្មវិធី​មួយ ឬ​ច្រើន​ដូច​ខាង​ក្រោម​ស្នើ​សិទ្ធិ ដើម្បី​ចូល​គណនី​របស់​អ្នក​ឥឡូវ និង​ពេល​អនាគត។"</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"តើ​អ្នក​ចង់​អនុញ្ញាត​សំណើ​នេះ?"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"ស្នើ​ចូល"</string>
-    <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string>
+    <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
     <string name="deny" msgid="2081879885755434506">"បដិសេធ"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"បាន​ស្នើ​សិទ្ធិ"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"បាន​ស្នើ​សិទ្ធិ\nសម្រាប់​គណនី <xliff:g id="ACCOUNT">%s</xliff:g> ។"</string>
@@ -1397,12 +1397,12 @@
     <string name="no_file_chosen" msgid="6363648562170759465">"គ្មាន​ឯកសារ​បាន​ជ្រើស"</string>
     <string name="reset" msgid="2448168080964209908">"កំណត់​ឡើងវិញ"</string>
     <string name="submit" msgid="1602335572089911941">"ដាក់​ស្នើ"</string>
-    <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បាន​បើក​របៀប​រថយន្ត"</string>
+    <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បាន​បើក​របៀប​រថយន្ត​"</string>
     <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"ប៉ះ​ ដើម្បី​ចេញ​ពី​របៀប​រថយន្ត​។"</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"ភ្ជាប់ ឬ​ហតស្ពត​សកម្ម"</string>
     <string name="tethered_notification_message" msgid="6857031760103062982">"ប៉ះ​ ដើម្បី​រៀបចំ។"</string>
     <string name="back_button_label" msgid="2300470004503343439">"ថយក្រោយ"</string>
-    <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់​"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"រំលង"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"ការ​ប្រើ​ទិន្នន័យ​ចល័ត​ខ្ពស់"</string>
     <string name="throttle_warning_notification_message" msgid="3340822228599337743">"ប៉ះ​ ដើម្បី​​ស្វែងយល់​បន្ថែម​អំពី​ការ​ប្រើ​​​ទិន្នន័យ​ចល័ត​។"</string>
@@ -1428,7 +1428,7 @@
     <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី​បច្ចុប្បន្ន​កំពុង​ប្រើ​ដោយ​កុំព្យូទ័រ។"</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"បច្ចុប្បន្ន​កាត​អេសឌី​កំពុង​ប្រើ​ដោយ​កុំព្យូទ័រ"</string>
     <string name="media_unknown_state" msgid="729192782197290385">"មិន​ស្គាល់​ស្ថានភាព​មេឌៀ​ខាង​ក្រៅ។"</string>
-    <string name="share" msgid="1778686618230011964">"ចែក​រំលែក"</string>
+    <string name="share" msgid="1778686618230011964">"ចែក​រំលែក​"</string>
     <string name="find" msgid="4808270900322985960">"រក"</string>
     <string name="websearch" msgid="4337157977400211589">"ស្វែងរក​តាម​បណ្ដាញ"</string>
     <string name="find_next" msgid="5742124618942193978">"រក​បន្ទាប់"</string>
@@ -1444,7 +1444,7 @@
     <string name="sync_undo_deletes" msgid="2941317360600338602">"មិន​ធ្វើ​ការ​លុប​វិញ"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"មិន​ធ្វើអ្វី​ទេ​ឥឡូវ"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"ជ្រើស​គណនី"</string>
-    <string name="add_account_label" msgid="2935267344849993553">"បន្ថែម​គណនី​ថ្មី"</string>
+    <string name="add_account_label" msgid="2935267344849993553">"បន្ថែម​គណនី​ថ្មី​​"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"បន្ថែម​គណនី"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"បង្កើន"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"បន្ថយ"</string>
@@ -1463,15 +1463,15 @@
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"បង្កើន​​ឆ្នាំ"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"បន្ថយ​ឆ្នាំ"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
-    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់"</string>
+    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
     <string name="keyboardview_keycode_done" msgid="1992571118466679775">"រួចរាល់"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ប្ដូរ​របៀប"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
-    <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើស​កម្មវិធី"</string>
+    <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើស​កម្មវិធី​​"</string>
     <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"មិន​អាច​ចាប់ផ្ដើម <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែក​ជា​មួយ"</string>
+    <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែក​ជា​មួយ​"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ចែក​រំលែក​ជា​មួយ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"គ្រប់គ្រង​ការ​រុញ។ ប៉ះ &amp; សង្កត់។"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"អូស​ ដើម្បី​ដោះ​សោ។"</string>
@@ -1485,7 +1485,7 @@
     <string name="storage_internal" msgid="4891916833657929263">"ឧបករណ៍​ផ្ទុក​ខាង​ក្នុង"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"កាត​អេសឌី"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី"</string>
-    <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល"</string>
+    <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>
     <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"បាន​បិទ​ទិន្នន័យ 2G​-3G"</string>
@@ -1542,7 +1542,7 @@
     <string name="media_route_status_available" msgid="6983258067194649391">"ទំនេរ"</string>
     <string name="media_route_status_not_available" msgid="6739899962681886401">"មិន​ទំនេរ"</string>
     <string name="media_route_status_in_use" msgid="4533786031090198063">"កំពុង​ប្រើ"</string>
-    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់​ជាប់"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់​ជាប់​"</string>
     <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"អេក្រង់ HDMI"</string>
     <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"#<xliff:g id="ID">%1$d</xliff:g> ត្រួត​គ្នា"</string>
     <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
@@ -1574,7 +1574,7 @@
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ព្យាយាម​លំនាំ​ច្រើន​ពេក"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"ដើម្បី​ដោះ​សោ ចូល​ក្នុង​គណនី Google ។"</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"ឈ្មោះ​អ្នក​ប្រើ (អ៊ី​ម៉ែ​ល​)"</string>
-    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់​"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"ចូល"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ភ្លេច​ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
@@ -1683,7 +1683,7 @@
     <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string>
     <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"​មិន​ស្គាល់​បញ្ឈរ"</string>
     <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"មិន​ស្គាល់​ទេសភាព"</string>
-    <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បាន​បោះ​បង់"</string>
+    <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បាន​បោះ​បង់​"</string>
     <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"កំហុស​ក្នុង​ការ​សរសេរ​មាតិកា"</string>
     <string name="reason_unknown" msgid="6048913880184628119">"មិន​ស្គាល់"</string>
     <string name="reason_service_unavailable" msgid="7824008732243903268">"មិន​បា​ន​បើក​សេវាកម្ម​បោះពុម្ព"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 71f55fb..3b275a5 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1695,7 +1695,7 @@
     <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"PIN ປະ​ຈຸ​ບັນ"</string>
     <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"ລະຫັດ PIN ໃໝ່"</string>
     <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"ຢືນຢັນລະຫັດ PIN ໃໝ່"</string>
-    <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາ​ລັບ​ການ​ປັບ​ປຸງ​ຂໍ້ຈໍາ​ກັດ"</string>
+    <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາ​ລັບ​ການ​ປັບ​ປຸງ​ຂໍ້ຈໍາ​ກັດ​"</string>
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN ບໍ່​ກົງກັນ. ລອງໃໝ່ອີກຄັ້ງ​."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN ​ສັ້ນ​ເກີນ​ໄປ​. ຕ້ອງມີຢ່າງໜ້ອຍ 4 ຫຼັກ​."</string>
   <plurals name="restr_pin_countdown">
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 489adb4..b8086be 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4806,6 +4806,8 @@
         <attr name="scaleX" />
         <!-- The amount to scale the group on X coordinate -->
         <attr name="scaleY" />
+        <!-- The alpha of the group (0 is transparent and 1 is opaque) -->
+        <attr name="alpha" />
     </declare-styleable>
 
     <!-- Defines the path used in Vector Drawables. -->
@@ -6719,4 +6721,17 @@
     <declare-styleable name="EdgeEffect">
         <attr name="colorPrimaryLight" />
     </declare-styleable>
+
+    <!-- Use <code>tv-input</code> as the root tag of the XML resource that describes an
+         {@link android.media.tv.TvInputService}, which is referenced from its
+         {@link android.media.tv.TvInputService#SERVICE_META_DATA} meta-data entry.
+         Described here are the attributes that can be included in that tag. -->
+    <declare-styleable name="TvInputService">
+        <!-- Component name of an activity for setup of this service.
+             The setup includes scanning channels and registering EPG data. -->
+        <attr name="setupActivity" format="string" />
+        <!-- Component name of an activity that allows the user to modify
+             the settings for this service. -->
+        <attr name="settingsActivity" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7fc2f49..f6ffd15 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2096,6 +2096,7 @@
   <public type="attr" name="windowSwipeToDismiss" id="0x10103f3" />
   <public type="attr" name="isGame" id="0x10103f4" />
   <public type="attr" name="allowEmbedded" id="0x10103f5" />
+  <public type="attr" name="setupActivity" id="0x10103f6"/>
 
 <!-- ===============================================================
      Resources added in version 21 of the platform
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8286ef9..9ff67b4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -419,6 +419,8 @@
         current device state, to send as an e-mail message.  It will take a little
         time from starting the bug report until it is ready to be sent; please be
         patient.</string>
+    <!-- Format for build summary info [CHAR LIMIT=NONE] -->
+    <string name="bugreport_status" translatable="false">%s (%s)</string>
 
     <!-- label for item that enables silent mode in phone options dialog -->
     <string name="global_action_toggle_silent_mode">Silent mode</string>
@@ -455,10 +457,10 @@
     <string name="android_system_label">Android System</string>
 
     <!-- Label for the user owner in the intent forwarding app. -->
-    <string name="user_owner_label">Personal</string>
+    <string name="user_owner_label">Personal apps</string>
 
     <!-- Label for a corporate profile in the intent forwarding app. -->
-    <string name="managed_profile_label">Work</string>
+    <string name="managed_profile_label">Android for Work</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_costMoney">Services that cost you money</string>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 2f51048..108334fa 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -518,7 +518,10 @@
     <style name="Widget.Quantum.ExpandableListView.White"/>
     <style name="Widget.Quantum.Gallery" parent="Widget.Gallery"/>
     <style name="Widget.Quantum.GestureOverlayView" parent="Widget.GestureOverlayView"/>
-    <style name="Widget.Quantum.GridView" parent="Widget.GridView"/>
+
+    <style name="Widget.Quantum.GridView" parent="Widget.GridView">
+        <item name="android:listSelector">?attr/selectableItemBackground</item>
+    </style>
 
     <style name="Widget.Quantum.CalendarView" parent="Widget.CalendarView">
         <item name="selectedWeekBackgroundColor">#330099FF</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6cd7cd2..8b1ca31 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1388,6 +1388,7 @@
   <java-symbol type="string" name="android_upgrading_title" />
   <java-symbol type="string" name="bugreport_title" />
   <java-symbol type="string" name="bugreport_message" />
+  <java-symbol type="string" name="bugreport_status" />
   <java-symbol type="string" name="faceunlock_multiple_failures" />
   <java-symbol type="string" name="global_action_power_off" />
   <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
index 5dc9ef8..433d4d2 100644
--- a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.util;
 
+import android.test.MoreAsserts;
+
+import java.util.Arrays;
 import junit.framework.TestCase;
 
 /**
@@ -77,4 +80,79 @@
         assertFalse(ArrayUtils.containsAll(new Object[] { }, new Object[] { null }));
         assertFalse(ArrayUtils.containsAll(new Object[] { A }, new Object[] { null }));
     }
+
+    public void testContainsInt() throws Exception {
+        assertTrue(ArrayUtils.contains(new int[] { 1, 2, 3 }, 1));
+        assertTrue(ArrayUtils.contains(new int[] { 1, 2, 3 }, 2));
+        assertTrue(ArrayUtils.contains(new int[] { 1, 2, 3 }, 3));
+
+        assertFalse(ArrayUtils.contains(new int[] { 1, 2, 3 }, 0));
+        assertFalse(ArrayUtils.contains(new int[] { 1, 2, 3 }, 4));
+        assertFalse(ArrayUtils.contains(new int[] { }, 2));
+    }
+
+    public void testAppendInt() throws Exception {
+        MoreAsserts.assertEquals(new int[] { 1 },
+                ArrayUtils.appendInt(null, 1));
+        MoreAsserts.assertEquals(new int[] { 1 },
+                ArrayUtils.appendInt(new int[] { }, 1));
+        MoreAsserts.assertEquals(new int[] { 1, 2 },
+                ArrayUtils.appendInt(new int[] { 1 }, 2));
+        MoreAsserts.assertEquals(new int[] { 1, 2 },
+                ArrayUtils.appendInt(new int[] { 1, 2 }, 1));
+    }
+
+    public void testRemoveInt() throws Exception {
+        assertNull(ArrayUtils.removeInt(null, 1));
+        MoreAsserts.assertEquals(new int[] { },
+                ArrayUtils.removeInt(new int[] { }, 1));
+        MoreAsserts.assertEquals(new int[] { 1, 2, 3, },
+                ArrayUtils.removeInt(new int[] { 1, 2, 3}, 4));
+        MoreAsserts.assertEquals(new int[] { 2, 3, },
+                ArrayUtils.removeInt(new int[] { 1, 2, 3}, 1));
+        MoreAsserts.assertEquals(new int[] { 1, 3, },
+                ArrayUtils.removeInt(new int[] { 1, 2, 3}, 2));
+        MoreAsserts.assertEquals(new int[] { 1, 2, },
+                ArrayUtils.removeInt(new int[] { 1, 2, 3}, 3));
+        MoreAsserts.assertEquals(new int[] { 2, 3, 1 },
+                ArrayUtils.removeInt(new int[] { 1, 2, 3, 1 }, 1));
+    }
+
+    public void testContainsLong() throws Exception {
+        assertTrue(ArrayUtils.contains(new long[] { 1, 2, 3 }, 1));
+        assertTrue(ArrayUtils.contains(new long[] { 1, 2, 3 }, 2));
+        assertTrue(ArrayUtils.contains(new long[] { 1, 2, 3 }, 3));
+
+        assertFalse(ArrayUtils.contains(new long[] { 1, 2, 3 }, 0));
+        assertFalse(ArrayUtils.contains(new long[] { 1, 2, 3 }, 4));
+        assertFalse(ArrayUtils.contains(new long[] { }, 2));
+    }
+
+    public void testAppendLong() throws Exception {
+        MoreAsserts.assertEquals(new long[] { 1 },
+                ArrayUtils.appendLong(null, 1));
+        MoreAsserts.assertEquals(new long[] { 1 },
+                ArrayUtils.appendLong(new long[] { }, 1));
+        MoreAsserts.assertEquals(new long[] { 1, 2 },
+                ArrayUtils.appendLong(new long[] { 1 }, 2));
+        MoreAsserts.assertEquals(new long[] { 1, 2 },
+                ArrayUtils.appendLong(new long[] { 1, 2 }, 1));
+    }
+
+    public void testRemoveLong() throws Exception {
+        assertNull(ArrayUtils.removeLong(null, 1));
+        MoreAsserts.assertEquals(new long[] { },
+                ArrayUtils.removeLong(new long[] { }, 1));
+        MoreAsserts.assertEquals(new long[] { 1, 2, 3, },
+                ArrayUtils.removeLong(new long[] { 1, 2, 3}, 4));
+        MoreAsserts.assertEquals(new long[] { 2, 3, },
+                ArrayUtils.removeLong(new long[] { 1, 2, 3}, 1));
+        MoreAsserts.assertEquals(new long[] { 1, 3, },
+                ArrayUtils.removeLong(new long[] { 1, 2, 3}, 2));
+        MoreAsserts.assertEquals(new long[] { 1, 2, },
+                ArrayUtils.removeLong(new long[] { 1, 2, 3}, 3));
+        MoreAsserts.assertEquals(new long[] { 2, 3, 1 },
+                ArrayUtils.removeLong(new long[] { 1, 2, 3, 1 }, 1));
+    }
+
 }
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
index c0c20e2..ca68e93 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
@@ -172,7 +172,8 @@
         final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
         final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
 
-        final ControllerImpl controller = new ControllerImpl(enabledItems);
+        final ControllerImpl controller = ControllerImpl.createFrom(
+                null /* currentInstance */, enabledItems);
 
         // switching-aware loop
         assertRotationOrder(controller, false /* onlyCurrentIme */,
@@ -214,9 +215,8 @@
                 disabledSubtypeUnawareIme, null);
     }
 
-    // This test is disabled until DynamicRotationList is enabled.
     @SmallTest
-    public void DISABLED_testControllerImplWithUserAction() throws Exception {
+    public void testControllerImplWithUserAction() throws Exception {
         final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
         final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0);
         final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
@@ -226,7 +226,8 @@
         final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
         final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
 
-        final ControllerImpl controller = new ControllerImpl(enabledItems);
+        final ControllerImpl controller = ControllerImpl.createFrom(
+                null /* currentInstance */, enabledItems);
 
         // === switching-aware loop ===
         assertRotationOrder(controller, false /* onlyCurrentIme */,
@@ -272,5 +273,26 @@
                 subtypeUnawareIme, null);
         assertNextInputMethod(controller, true /* onlyCurrentIme */,
                 switchUnawareJapaneseIme_ja_JP, null);
+
+        // Rotation order should be preserved when created with the same subtype list.
+        final List<ImeSubtypeListItem> sameEnabledItems = createEnabledImeSubtypes();
+        final ControllerImpl newController = ControllerImpl.createFrom(controller,
+                sameEnabledItems);
+        assertRotationOrder(newController, false /* onlyCurrentIme */,
+                japaneseIme_ja_JP, latinIme_fr, latinIme_en_US);
+        assertRotationOrder(newController, false /* onlyCurrentIme */,
+                switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme,
+                switchUnawareJapaneseIme_ja_JP);
+
+        // Rotation order should be initialized when created with a different subtype list.
+        final List<ImeSubtypeListItem> differentEnabledItems = Arrays.asList(
+                latinIme_en_US, latinIme_fr, switchingUnawarelatinIme_en_UK,
+                switchUnawareJapaneseIme_ja_JP);
+        final ControllerImpl anotherController = ControllerImpl.createFrom(controller,
+                differentEnabledItems);
+        assertRotationOrder(anotherController, false /* onlyCurrentIme */,
+                latinIme_en_US, latinIme_fr);
+        assertRotationOrder(anotherController, false /* onlyCurrentIme */,
+                switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP);
     }
 }
diff --git a/data/fonts/Roboto-Black.ttf b/data/fonts/Roboto-Black.ttf
index 2cdbe43..cb905bc 100644
--- a/data/fonts/Roboto-Black.ttf
+++ b/data/fonts/Roboto-Black.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf
index 15c9b4e..68822ca 100644
--- a/data/fonts/Roboto-Bold.ttf
+++ b/data/fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf
index a0abf30..aebf8eb 100644
--- a/data/fonts/Roboto-BoldItalic.ttf
+++ b/data/fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf
index 67b5394..2041cbc 100644
--- a/data/fonts/Roboto-Italic.ttf
+++ b/data/fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Light.ttf b/data/fonts/Roboto-Light.ttf
index d9fb64a..aa45340 100644
--- a/data/fonts/Roboto-Light.ttf
+++ b/data/fonts/Roboto-Light.ttf
Binary files differ
diff --git a/data/fonts/Roboto-LightItalic.ttf b/data/fonts/Roboto-LightItalic.ttf
index 1fd1d31..a85444f 100644
--- a/data/fonts/Roboto-LightItalic.ttf
+++ b/data/fonts/Roboto-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Medium.ttf b/data/fonts/Roboto-Medium.ttf
index c63c115..a3c1a1f 100644
--- a/data/fonts/Roboto-Medium.ttf
+++ b/data/fonts/Roboto-Medium.ttf
Binary files differ
diff --git a/data/fonts/Roboto-MediumItalic.ttf b/data/fonts/Roboto-MediumItalic.ttf
index cd7c835..a30aa0c 100644
--- a/data/fonts/Roboto-MediumItalic.ttf
+++ b/data/fonts/Roboto-MediumItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf
index 9cb4a5a..0e58508 100644
--- a/data/fonts/Roboto-Regular.ttf
+++ b/data/fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Thin.ttf b/data/fonts/Roboto-Thin.ttf
index f02f100..8779333 100644
--- a/data/fonts/Roboto-Thin.ttf
+++ b/data/fonts/Roboto-Thin.ttf
Binary files differ
diff --git a/data/fonts/Roboto-ThinItalic.ttf b/data/fonts/Roboto-ThinItalic.ttf
index 12a2ce0..b79cb26 100644
--- a/data/fonts/Roboto-ThinItalic.ttf
+++ b/data/fonts/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Bold.ttf b/data/fonts/RobotoCondensed-Bold.ttf
index 1079af6..3e06c7c 100644
--- a/data/fonts/RobotoCondensed-Bold.ttf
+++ b/data/fonts/RobotoCondensed-Bold.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-BoldItalic.ttf b/data/fonts/RobotoCondensed-BoldItalic.ttf
index e7f13c2..aaf9fe0 100644
--- a/data/fonts/RobotoCondensed-BoldItalic.ttf
+++ b/data/fonts/RobotoCondensed-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Italic.ttf b/data/fonts/RobotoCondensed-Italic.ttf
index 7fa04481..d2b611f 100644
--- a/data/fonts/RobotoCondensed-Italic.ttf
+++ b/data/fonts/RobotoCondensed-Italic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Light.ttf b/data/fonts/RobotoCondensed-Light.ttf
index 96b75dd..d4eb198 100644
--- a/data/fonts/RobotoCondensed-Light.ttf
+++ b/data/fonts/RobotoCondensed-Light.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-LightItalic.ttf b/data/fonts/RobotoCondensed-LightItalic.ttf
index 7a2c164..a08f3f4 100644
--- a/data/fonts/RobotoCondensed-LightItalic.ttf
+++ b/data/fonts/RobotoCondensed-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Regular.ttf b/data/fonts/RobotoCondensed-Regular.ttf
index 734cc40..b9fc49c 100644
--- a/data/fonts/RobotoCondensed-Regular.ttf
+++ b/data/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/docs/html/distribute/engage/deep-linking.jd b/docs/html/distribute/engage/deep-linking.jd
index 50728c5..0417ba1 100644
--- a/docs/html/distribute/engage/deep-linking.jd
+++ b/docs/html/distribute/engage/deep-linking.jd
@@ -68,8 +68,6 @@
   <h2 id="related-resources">
     Related Resources
   </h2>
-
-
 </div>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
diff --git a/docs/html/distribute/essentials/quality/core.jd b/docs/html/distribute/essentials/quality/core.jd
index c301f8c..cfe1a2a 100644
--- a/docs/html/distribute/essentials/quality/core.jd
+++ b/docs/html/distribute/essentials/quality/core.jd
@@ -234,9 +234,7 @@
   </tr>
 </table>
 
-<h3>
-  Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/essentials/corequalityguidelines/visualdesign"
@@ -509,9 +507,7 @@
   </tr>
 </table>
 
-<h3>
-  Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/essentials/corequalityguidelines/functionality"
@@ -670,9 +666,7 @@
   </tr>
 </table>
 
-<h3>
-  Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/essentials/core/performance" data-sortorder="-timestamp"
@@ -819,9 +813,7 @@
   </tr>
 </table>
 
-<h3>
-  Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/essentials/core/play" data-sortorder="-timestamp"
diff --git a/docs/html/distribute/essentials/quality/tablets.jd b/docs/html/distribute/essentials/quality/tablets.jd
index 966c462..2b2a5ae 100644
--- a/docs/html/distribute/essentials/quality/tablets.jd
+++ b/docs/html/distribute/essentials/quality/tablets.jd
@@ -158,7 +158,7 @@
 multi-pane UI for tablets (see next section).</li>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/optimize"
@@ -219,7 +219,7 @@
 <code>sw600dp</code>/<code>sw720</code>).</li>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/extrascreen"
@@ -308,7 +308,7 @@
 it will request the {@code xxhdpi} version of the launcher icon.</li>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/assets"
@@ -345,7 +345,7 @@
 or just centering the icon within the transparent button.</li>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/fonts"
@@ -371,7 +371,7 @@
 possible.</li>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/widgets"
@@ -458,7 +458,7 @@
   </li>
 </ol>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/versions"
@@ -528,7 +528,7 @@
   as needed.
 </p>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/hardware"
@@ -560,7 +560,7 @@
 <a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html"><code>&lt;compatible-screens&gt;</code></a>
 element in your app.</p>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/tabletscreens"
@@ -689,7 +689,7 @@
   </li>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/showcase"
@@ -799,7 +799,7 @@
   recommended.
 </p>
 
-<h3 class="clearfloat">Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/essentials/tabletguidelines/googleplay"
   data-sortOrder="-timestamp"
diff --git a/docs/html/distribute/googleplay/edu/about.jd b/docs/html/distribute/googleplay/edu/about.jd
index 1c003cf..e73356e 100644
--- a/docs/html/distribute/googleplay/edu/about.jd
+++ b/docs/html/distribute/googleplay/edu/about.jd
@@ -109,7 +109,7 @@
 <p style="clear:both">
 </p>
 <div class="headerLine">
-<h2>Related Resources</h2>
+<h2 id="related-resources">Related Resources</h2>
 </div>
 
 <div class="dynamic-grid">
diff --git a/docs/html/distribute/tools/launch-checklist.jd b/docs/html/distribute/tools/launch-checklist.jd
index 3f6b1a6..f310800 100644
--- a/docs/html/distribute/tools/launch-checklist.jd
+++ b/docs/html/distribute/tools/launch-checklist.jd
@@ -85,9 +85,7 @@
   Play.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/understanding"
@@ -110,9 +108,7 @@
   repeated violations, termination of your developer account.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/policies" data-sortorder=
@@ -154,9 +150,7 @@
   should exhibit.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/quality" data-sortorder=
@@ -212,9 +206,7 @@
   no changes are required in your app binary.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/rating" data-sortorder=
@@ -280,9 +272,7 @@
   Checklist</a> for key steps and considerations in the localization process.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/country" data-sortorder=
@@ -335,9 +325,7 @@
   on your code when building your release-ready APK.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/size" data-sortorder=
@@ -387,9 +375,7 @@
   <a href="{@docRoot}about/dashboards/index.html">Device Dashboard</a> charts.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/platform" data-sortorder=
@@ -450,9 +436,7 @@
   set up a Google Wallet Merchant Account</a> before you can publish.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/price" data-sortorder=
@@ -485,9 +469,7 @@
   complete and test your implementation before creating your release-ready APK.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/purchasemethod"
@@ -517,9 +499,7 @@
   available currencies through the Developer Console.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/setprice" data-sortorder=
@@ -599,9 +579,7 @@
   listing.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/localization"
@@ -659,9 +637,7 @@
   publishing date.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/graphics" data-sortorder=
@@ -701,7 +677,7 @@
   Developer Console. If necessary, you can replace an APK with a more recent
   version before publishing.
 </p>
-<!--<h3>Related resources</h3>
+<!--<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/toolsreference/launchchecklist/build"
@@ -815,9 +791,7 @@
   elsewhere.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/productdetails"
@@ -853,9 +827,7 @@
   available.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/badges" data-sortorder=
@@ -959,9 +931,7 @@
   linking from your promotional campaigns.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/launchchecklist/finalchecks"
@@ -1063,7 +1033,7 @@
 </ul>
 </ul>
 
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/toolsreference/launchchecklist/afterlaunch"
diff --git a/docs/html/distribute/tools/localization-checklist.jd b/docs/html/distribute/tools/localization-checklist.jd
index 569ed02..08a8143 100644
--- a/docs/html/distribute/tools/localization-checklist.jd
+++ b/docs/html/distribute/tools/localization-checklist.jd
@@ -84,9 +84,7 @@
   development, translation, testing, and marketing efforts to these markets.
 </p>
 
-<h3 id="related-resources">
-  Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/localizationchecklist/identifylocales"
@@ -224,9 +222,7 @@
   directories, without language or locale qualifiers.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/tools/loc/designforloc" data-sortorder="-timestamp"
@@ -399,9 +395,7 @@
 
 &lt;/resources&gt;
 </pre>
-<h3 class="clearfloat">
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/localizationchecklist/managestrings"
@@ -570,9 +564,7 @@
   <img src="{@docRoot}images/gp-localization-trans-0.png" class="border-img">
 </div>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/localizationchecklist/translatestrings"
@@ -690,7 +682,7 @@
   your localized apps. One way to do that is through beta testing with regional
   users &mdash; Google Play can help you do this. <!-- </p>
 
-<h3 class="clearfloat">Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/toolsreference/localizationchecklist/test"
@@ -887,9 +879,7 @@
   helpful reminders for a successful localized launch.
 </p>
 
-<h3>
-  Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13" data-query=
 "collection:distribute/toolsreference/localizationchecklist/preplaunch"
@@ -968,7 +958,7 @@
   "{@docRoot}distribute/tools/launch-checklist.html">Launch Checklist</a> to
   learn more about how to plan, build, and launch your app on Google Play.
 </p>
-<h3 class="clearfloat">Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
 
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/toolsreference/localizationchecklist/supportlaunch"
diff --git a/docs/html/distribute/tools/promote/badge-files.jd b/docs/html/distribute/tools/promote/badge-files.jd
index b481802..e65e698 100644
--- a/docs/html/distribute/tools/promote/badge-files.jd
+++ b/docs/html/distribute/tools/promote/badge-files.jd
@@ -21,9 +21,10 @@
 
        <a href="{@docRoot}downloads/brand/v2/english_get.ai">English (English)</a><br/>
 
+       <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
+
        <a href="{@docRoot}downloads/brand/v2/amharic_get.ai">ኣማርኛ (Amharic)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
 <!--
        <a href="{@docRoot}downloads/brand/ar_generic_rgb_wo.ai">العربية (Arabic)</a><br/>
 -->
@@ -286,6 +287,3 @@
 <p>To quickly create a badge that links to your apps on Google Play,
 use the <a
 href="{@docRoot}distribute/tools/promote/badges.html">Googe Play badge generator</a>.</p>
-    
-    
-    
\ No newline at end of file
diff --git a/docs/html/guide/components/fundamentals.jd b/docs/html/guide/components/fundamentals.jd
index 9ac063e..fd1a7a8 100644
--- a/docs/html/guide/components/fundamentals.jd
+++ b/docs/html/guide/components/fundamentals.jd
@@ -335,8 +335,8 @@
 {@link android.content.Intent} to start activities, services, and broadcast receivers. You can do so
 by explicitly naming the target component (using the component class name) in the intent. However,
 the real power of intents lies in the concept of <em>implicit intents</em>. An implicit intent
-simply describe the type of action to perform (and optionally, the data upon which you’d like to
-perform the action) and allow the system to find a component on the device that can perform the
+simply describes the type of action to perform (and, optionally, the data upon which you’d like to
+perform the action) and allows the system to find a component on the device that can perform the
 action and start it. If there are multiple components that can perform the action described by the
 intent, then the user selects which one to use.</p>
 
diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd
index e9caa44..e748b12 100644
--- a/docs/html/tools/device.jd
+++ b/docs/html/tools/device.jd
@@ -280,6 +280,10 @@
     <td><code>0fce</code></td>
   </tr>
   <tr>
+    <td>Sony Mobile Communications</td>
+    <td><code>0fce</code></td>
+  </tr>
+  <tr>
     <td>Teleepoch</td>
     <td><code>2340</code></td>
   </tr>
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 6802b9a..11d3165 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.content.res.AssetManager;
+
 import java.io.File;
 
 /**
@@ -58,11 +60,17 @@
         }
     }
 
-    public boolean addFont(File path) {
-        return nAddFont(mNativePtr, path.getAbsolutePath());
+    public boolean addFont(String path) {
+        return nAddFont(mNativePtr, path);
     }
 
-    static native long nCreateFamily(String lang, int variant);
-    static native void nUnrefFamily(long nativePtr);
-    static native boolean nAddFont(long nativeFamily, String path);
+    public boolean addFontFromAsset(AssetManager mgr, String path) {
+        return nAddFontFromAsset(mNativePtr, mgr, path);
+    }
+
+    private static native long nCreateFamily(String lang, int variant);
+    private static native void nUnrefFamily(long nativePtr);
+    private static native boolean nAddFont(long nativeFamily, String path);
+    private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr,
+            String path);
 }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 2b07c3f..cb48de2 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -178,6 +178,15 @@
      * @return The new typeface.
      */
     public static Typeface createFromAsset(AssetManager mgr, String path) {
+        if (sFallbackFonts != null) {
+            FontFamily fontFamily = new FontFamily();
+            if (fontFamily.addFontFromAsset(mgr, path)) {
+                FontFamily[] families = { fontFamily };
+                return createFromFamiliesWithDefault(families);
+            } else {
+                return null;
+            }
+        }
         return new Typeface(nativeCreateFromAsset(mgr, path));
     }
 
@@ -188,7 +197,7 @@
      * @return The new typeface.
      */
     public static Typeface createFromFile(File path) {
-        return new Typeface(nativeCreateFromFile(path.getAbsolutePath()));
+        return createFromFile(path.getAbsolutePath());
     }
 
     /**
@@ -198,6 +207,15 @@
      * @return The new typeface.
      */
     public static Typeface createFromFile(String path) {
+        if (sFallbackFonts != null) {
+            FontFamily fontFamily = new FontFamily();
+            if (fontFamily.addFont(path)) {
+                FontFamily[] families = { fontFamily };
+                return createFromFamiliesWithDefault(families);
+            } else {
+                return null;
+            }
+        }
         return new Typeface(nativeCreateFromFile(path));
     }
 
@@ -247,7 +265,7 @@
         // TODO: expand to handle attributes like lang and variant
         FontFamily fontFamily = new FontFamily(family.lang, family.variant);
         for (String fontFile : family.fontFiles) {
-            fontFamily.addFont(new File(fontFile));
+            fontFamily.addFont(fontFile);
         }
         return fontFamily;
     }
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index a37ceef..e8024f7 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -260,7 +260,7 @@
                 continue;
             }
 
-            if ((drawable = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme)) == null) {
+            if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
                 Log.w("drawable", "Bad element under <animated-rotate>: "
                         + parser .getName());
             }
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 42872e9..a5a074c 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -301,7 +301,7 @@
                                 + ": <item> tag requires a 'drawable' attribute or "
                                 + "child tag defining a drawable");
             }
-            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
         final AnimationDrawable anim;
@@ -355,7 +355,7 @@
                                 + ": <item> tag requires a 'drawable' attribute or "
                                 + "child tag defining a drawable");
             }
-            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
         return mState.addStateSet(states, dr, keyframeId);
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index da4bc10..0ee253a 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -293,7 +293,7 @@
                             ": <item> tag requires a 'drawable' attribute or child tag" +
                             " defining a drawable");
                 }
-                dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
             
             mAnimationState.addFrame(dr, duration);
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 3dbd235..3ac9972 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -95,7 +95,7 @@
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
-            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
         if (dr == null) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index cc2a595..f29b9f0 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -892,13 +892,9 @@
      * Create a drawable from an inputstream
      */
     public static Drawable createFromStream(InputStream is, String srcName) {
-        return createFromStreamThemed(is, srcName, null);
-    }
-
-    public static Drawable createFromStreamThemed(InputStream is, String srcName, Theme theme) {
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
         try {
-            return createFromResourceStreamThemed(null, null, is, srcName, theme);
+            return createFromResourceStream(null, null, is, srcName);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
@@ -910,14 +906,9 @@
      */
     public static Drawable createFromResourceStream(Resources res, TypedValue value,
             InputStream is, String srcName) {
-        return createFromResourceStreamThemed(res, value, is, srcName, null);
-    }
-
-    public static Drawable createFromResourceStreamThemed(Resources res, TypedValue value,
-            InputStream is, String srcName, Theme theme) {
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
         try {
-            return createFromResourceStreamThemed(res, value, is, srcName, null, theme);
+            return createFromResourceStream(res, value, is, srcName);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
@@ -929,11 +920,6 @@
      */
     public static Drawable createFromResourceStream(Resources res, TypedValue value,
             InputStream is, String srcName, BitmapFactory.Options opts) {
-        return createFromResourceStreamThemed(res, value, is, srcName, opts, null);
-    }
-
-    public static Drawable createFromResourceStreamThemed(Resources res, TypedValue value,
-            InputStream is, String srcName, BitmapFactory.Options opts, Theme theme) {
         if (is == null) {
             return null;
         }
@@ -981,15 +967,15 @@
      */
     public static Drawable createFromXml(Resources r, XmlPullParser parser)
             throws XmlPullParserException, IOException {
-        return createFromXmlThemed(r, parser, null);
+        return createFromXml(r, parser, null);
     }
 
     /**
-     * Create a themed drawable from an XML document. For more information on
-     * how to create resources in XML, see
+     * Create a drawable from an XML document using an optional {@link Theme}.
+     * For more information on how to create resources in XML, see
      * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
      */
-    public static Drawable createFromXmlThemed(Resources r, XmlPullParser parser, Theme theme)
+    public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)
             throws XmlPullParserException, IOException {
         AttributeSet attrs = Xml.asAttributeSet(parser);
 
@@ -1003,7 +989,7 @@
             throw new XmlPullParserException("No start tag found");
         }
 
-        Drawable drawable = createFromXmlInnerThemed(r, parser, attrs, theme);
+        Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
 
         if (drawable == null) {
             throw new RuntimeException("Unknown initial tag: " + parser.getName());
@@ -1019,16 +1005,17 @@
      */
     public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
             throws XmlPullParserException, IOException {
-        return createFromXmlInnerThemed(r, parser, attrs, null);
+        return createFromXmlInner(r, parser, attrs, null);
     }
 
     /**
-     * Create a themed drawable from inside an XML document. Called on a parser
-     * positioned at a tag in an XML document, tries to create a Drawable from
-     * that tag. Returns null if the tag is not a valid drawable.
+     * Create a drawable from inside an XML document using an optional
+     * {@link Theme}. Called on a parser positioned at a tag in an XML
+     * document, tries to create a Drawable from that tag. Returns {@code null}
+     * if the tag is not a valid drawable.
      */
-    public static Drawable createFromXmlInnerThemed(Resources r, XmlPullParser parser,
-            AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
+    public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
         final Drawable drawable;
 
         final String name = parser.getName();
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index b2d61ec..1512da5b 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -612,7 +612,9 @@
             case LINE: {
                 RectF r = mRect;
                 float y = r.centerY();
-                canvas.drawLine(r.left, y, r.right, y, mStrokePaint);
+                if (haveStroke) {
+                    canvas.drawLine(r.left, y, r.right, y, mStrokePaint);
+                }
                 break;
             }
             case RING:
@@ -1431,7 +1433,7 @@
         public int mChangingConfigurations;
         public int mShape = RECTANGLE;
         public int mGradient = LINEAR_GRADIENT;
-        public int mAngle;
+        public int mAngle = 0;
         public Orientation mOrientation;
         public ColorStateList mColorStateList;
         public ColorStateList mStrokeColorStateList;
@@ -1439,12 +1441,12 @@
         public int[] mTempColors; // no need to copy
         public float[] mTempPositions; // no need to copy
         public float[] mPositions;
-        public int mStrokeWidth = -1;   // if >= 0 use stroking.
-        public float mStrokeDashWidth;
-        public float mStrokeDashGap;
-        public float mRadius;    // use this if mRadiusArray is null
-        public float[] mRadiusArray;
-        public Rect mPadding;
+        public int mStrokeWidth = -1; // if >= 0 use stroking.
+        public float mStrokeDashWidth = 0.0f;
+        public float mStrokeDashGap = 0.0f;
+        public float mRadius = 0.0f; // use this if mRadiusArray is null
+        public float[] mRadiusArray = null;
+        public Rect mPadding = null;
         public int mWidth = -1;
         public int mHeight = -1;
         public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 2fa5929..9e0ab86 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -111,7 +111,7 @@
                         + ": <inset> tag requires a 'drawable' attribute or "
                         + "child tag defining a drawable");
             }
-            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
         if (dr == null) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 75cb0a00..27f0a9d 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -211,7 +211,7 @@
                             + ": <item> tag requires a 'drawable' attribute or "
                             + "child tag defining a drawable");
                 }
-                dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
 
             addLayer(dr, themeAttrs, id, left, top, right, bottom);
diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java
index 9f6c0ad..7271b0e 100644
--- a/graphics/java/android/graphics/drawable/LevelListDrawable.java
+++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java
@@ -134,7 +134,7 @@
                                     + ": <item> tag requires a 'drawable' attribute or "
                                     + "child tag defining a drawable");
                 }
-                dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
 
             mLevelListState.addLevel(low, high, dr);
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 5f9d1cd..06aeb98 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -438,7 +438,7 @@
                 continue;
             }
 
-            if ((drawable = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme)) == null) {
+            if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
                 Log.w("drawable", "Bad element under <rotate>: "
                         + parser .getName());
             }
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 4c4d9af..f090c11 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -108,7 +108,7 @@
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
-            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
         if (dr == null) {
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 99ab4dd..024f77c 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -291,41 +291,10 @@
         return mShapeState.mAlpha;
     }
 
-    /**
-     * Specifies a tint for this drawable.
-     * <p>
-     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
-     * tint.
-     *
-     * @param tint Color state list to use for tinting this drawable, or null to
-     *            clear the tint
-     */
-    public void setTint(ColorStateList tint) {
-        if (mShapeState.mTint != tint) {
+    @Override
+    public void setTint(ColorStateList tint, Mode tintMode) {
+        if (mShapeState.mTint != tint || mShapeState.mTintMode != tintMode) {
             mShapeState.mTint = tint;
-            updateTintFilter();
-            invalidateSelf();
-        }
-    }
-
-    /**
-     * Returns the tint color for this drawable.
-     *
-     * @return Color state list to use for tinting this drawable, or null if
-     *         none set
-     */
-    public ColorStateList getTint() {
-        return mShapeState.mTint;
-    }
-
-    /**
-     * Specifies the blending mode used to apply tint.
-     *
-     * @param tintMode A Porter-Duff blending mode
-     * @hide Pending finalization of supported Modes
-     */
-    public void setTintMode(Mode tintMode) {
-        if (mShapeState.mTintMode != tintMode) {
             mShapeState.mTintMode = tintMode;
             updateTintFilter();
             invalidateSelf();
@@ -350,16 +319,6 @@
         }
     }
 
-    /**
-     * Returns the blending mode used to apply tint.
-     *
-     * @return The Porter-Duff blending mode used to apply tint.
-     * @hide Pending finalization of supported Modes
-     */
-    public Mode getTintMode() {
-        return mShapeState.mTintMode;
-    }
-
     @Override
     public void setColorFilter(ColorFilter cf) {
         mShapeState.mPaint.setColorFilter(cf);
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index f22a063..b2fac9b 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -185,7 +185,7 @@
                                     + ": <item> tag requires a 'drawable' attribute or "
                                     + "child tag defining a drawable");
                 }
-                dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
 
             mStateListState.addStateSet(states, dr);
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index afd529c..c6c5b31 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -18,6 +18,7 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -40,6 +41,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Stack;
 
 /**
  * This lets you create a drawable based on an XML vector graphic It can be
@@ -129,9 +131,9 @@
     private static final int LINEJOIN_ROUND = 1;
     private static final int LINEJOIN_BEVEL = 2;
 
-    private final VectorDrawableState mVectorState;
+    private static final boolean DBG_VECTOR_DRAWABLE = false;
 
-    private int mAlpha = 0xFF;
+    private final VectorDrawableState mVectorState;
 
     public VectorDrawable() {
         mVectorState = new VectorDrawableState(null);
@@ -161,9 +163,8 @@
 
     @Override
     public void setAlpha(int alpha) {
-        // TODO correct handling of transparent
-        if (mAlpha != alpha) {
-            mAlpha = alpha;
+        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
+            mVectorState.mVPathRenderer.setRootAlpha(alpha);
             invalidateSelf();
         }
     }
@@ -270,6 +271,13 @@
         return null;
     }
 
+    private static int applyAlpha(int color, float alpha) {
+        int alphaBytes = Color.alpha(color);
+        color &= 0x00FFFFFF;
+        color |= ((int) (alphaBytes * alpha)) << 24;
+        return color;
+    }
+
     private VPathRenderer inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
             Theme theme) throws XmlPullParserException, IOException {
         final VPathRenderer pathRenderer = new VPathRenderer();
@@ -279,12 +287,17 @@
         boolean noGroupTag = true;
         boolean noPathTag = true;
 
-        VGroup currentGroup = new VGroup();
+        // Use a stack to help to build the group tree.
+        // The top of the stack is always the current group.
+        final Stack<VGroup> groupStack = new Stack<VGroup>();
+        groupStack.push(pathRenderer.mRootGroup);
 
         int eventType = parser.getEventType();
         while (eventType != XmlPullParser.END_DOCUMENT) {
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
+                final VGroup currentGroup = groupStack.peek();
+
                 if (SHAPE_PATH.equals(tagName)) {
                     final VPath path = new VPath();
                     path.inflate(res, attrs, theme);
@@ -297,18 +310,24 @@
                     pathRenderer.parseViewport(res, attrs);
                     noViewportTag = false;
                 } else if (SHAPE_GROUP.equals(tagName)) {
-                    currentGroup = new VGroup();
-                    currentGroup.inflate(res, attrs, theme);
-                    pathRenderer.mGroupList.add(currentGroup);
+                    VGroup newChildGroup = new VGroup();
+                    newChildGroup.inflate(res, attrs, theme);
+                    currentGroup.mChildGroupList.add(newChildGroup);
+                    groupStack.push(newChildGroup);
                     noGroupTag = false;
                 }
+            } else if (eventType == XmlPullParser.END_TAG) {
+                final String tagName = parser.getName();
+                if (SHAPE_GROUP.equals(tagName)) {
+                    groupStack.pop();
+                }
             }
-
             eventType = parser.next();
         }
 
-        if (noGroupTag && !noPathTag) {
-            pathRenderer.mGroupList.add(currentGroup);
+        // Print the tree out for debug.
+        if (DBG_VECTOR_DRAWABLE) {
+            printGroupTree(pathRenderer.mRootGroup, 0);
         }
 
         if (noSizeTag || noViewportTag || noPathTag) {
@@ -338,6 +357,21 @@
         return pathRenderer;
     }
 
+    private void printGroupTree(VGroup currentGroup, int level) {
+        String indent = "";
+        for (int i = 0 ; i < level ; i++) {
+            indent += "    ";
+        }
+        // Print the current node
+        Log.v(LOGTAG, indent + "current group is :" +  currentGroup.getName()
+                + " rotation is " + currentGroup.mRotate);
+        Log.v(LOGTAG, indent + "matrix is :" +  currentGroup.getLocalMatrix().toString());
+        // Then print all the children
+        for (int i = 0 ; i < currentGroup.mChildGroupList.size(); i++) {
+            printGroupTree(currentGroup.mChildGroupList.get(i), level + 1);
+        }
+    }
+
     private void setPathRenderer(VPathRenderer pathRenderer) {
         mVectorState.mVPathRenderer = pathRenderer;
     }
@@ -350,6 +384,7 @@
         public VectorDrawableState(VectorDrawableState copy) {
             if (copy != null) {
                 mChangingConfigurations = copy.mChangingConfigurations;
+                // TODO: Make sure the constant state are handled correctly.
                 mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
                 mPadding = new Rect(copy.mPadding);
             }
@@ -377,28 +412,51 @@
     }
 
     private static class VPathRenderer {
+        /* Right now the internal data structure is organized as a tree.
+         * Each node can be a group node, or a path.
+         * A group node can have groups or paths as children, but a path node has
+         * no children.
+         * One example can be:
+         *                 Root Group
+         *                /    |     \
+         *           Group    Path    Group
+         *          /     \             |
+         *         Path   Path         Path
+         *
+         */
+        private final VGroup mRootGroup;
+
         private final Path mPath = new Path();
         private final Path mRenderPath = new Path();
-        private final Matrix mMatrix = new Matrix();
+        private static final Matrix IDENTITY_MATRIX = new Matrix();
 
         private Paint mStrokePaint;
         private Paint mFillPaint;
         private ColorFilter mColorFilter;
         private PathMeasure mPathMeasure;
 
-        final ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+        private float mBaseWidth = 0;
+        private float mBaseHeight = 0;
+        private float mViewportWidth = 0;
+        private float mViewportHeight = 0;
+        private int mRootAlpha = 0xFF;
 
-        float mBaseWidth = 0;
-        float mBaseHeight = 0;
-        float mViewportWidth = 0;
-        float mViewportHeight = 0;
+        private final Matrix mFinalPathMatrix = new Matrix();
 
         public VPathRenderer() {
+            mRootGroup = new VGroup();
+        }
+
+        public void setRootAlpha(int alpha) {
+            mRootAlpha = alpha;
+        }
+
+        public int getRootAlpha() {
+            return mRootAlpha;
         }
 
         public VPathRenderer(VPathRenderer copy) {
-            mGroupList.addAll(copy.mGroupList);
-
+            mRootGroup = copy.mRootGroup;
             mBaseWidth = copy.mBaseWidth;
             mBaseHeight = copy.mBaseHeight;
             mViewportWidth = copy.mViewportHeight;
@@ -406,33 +464,59 @@
         }
 
         public boolean canApplyTheme() {
-            final ArrayList<VGroup> groups = mGroupList;
-            for (int i = groups.size() - 1; i >= 0; i--) {
-                final ArrayList<VPath> paths = groups.get(i).mVGList;
-                for (int j = paths.size() - 1; j >= 0; j--) {
-                    final VPath path = paths.get(j);
-                    if (path.canApplyTheme()) {
-                        return true;
-                    }
+            // If one of the paths can apply theme, then return true;
+            return recursiveCanApplyTheme(mRootGroup);
+        }
+
+        private boolean recursiveCanApplyTheme(VGroup currentGroup) {
+            // We can do a tree traverse here, if there is one path return true,
+            // then we return true for the whole tree.
+            final ArrayList<VPath> paths = currentGroup.mPathList;
+            for (int j = paths.size() - 1; j >= 0; j--) {
+                final VPath path = paths.get(j);
+                if (path.canApplyTheme()) {
+                    return true;
                 }
             }
 
+            final ArrayList<VGroup> childGroups = currentGroup.mChildGroupList;
+
+            for (int i = 0; i < childGroups.size(); i++) {
+                VGroup childGroup = childGroups.get(i);
+                if (childGroup.canApplyTheme()
+                        || recursiveCanApplyTheme(childGroup)) {
+                    return true;
+                }
+            }
             return false;
         }
 
         public void applyTheme(Theme t) {
-            final ArrayList<VGroup> groups = mGroupList;
-            for (int i = groups.size() - 1; i >= 0; i--) {
-                VGroup currentGroup = groups.get(i);
-                currentGroup.applyTheme(t);
-                final ArrayList<VPath> paths = currentGroup.mVGList;
-                for (int j = paths.size() - 1; j >= 0; j--) {
-                    final VPath path = paths.get(j);
-                    if (path.canApplyTheme()) {
-                        path.applyTheme(t);
-                    }
+            // Apply theme to every path of the tree.
+            recursiveApplyTheme(mRootGroup, t);
+        }
+
+        private void recursiveApplyTheme(VGroup currentGroup, Theme t) {
+            // We can do a tree traverse here, apply theme to all paths which
+            // can apply theme.
+            final ArrayList<VPath> paths = currentGroup.mPathList;
+            for (int j = paths.size() - 1; j >= 0; j--) {
+                final VPath path = paths.get(j);
+                if (path.canApplyTheme()) {
+                    path.applyTheme(t);
                 }
             }
+
+            final ArrayList<VGroup> childGroups = currentGroup.mChildGroupList;
+
+            for (int i = 0; i < childGroups.size(); i++) {
+                VGroup childGroup = childGroups.get(i);
+                if (childGroup.canApplyTheme()) {
+                    childGroup.applyTheme(t);
+                }
+                recursiveApplyTheme(childGroup, t);
+            }
+
         }
 
         public void setColorFilter(ColorFilter colorFilter) {
@@ -448,34 +532,36 @@
 
         }
 
-        public void draw(Canvas canvas, int w, int h) {
-            if (mGroupList == null || mGroupList.size() == 0) {
-                Log.e(LOGTAG,"There is no group to draw");
-                return;
-            }
+        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
+                float currentAlpha, Canvas canvas, int w, int h) {
+            // Calculate current group's matrix by preConcat the parent's and
+            // and the current one on the top of the stack.
+            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+            // Mi the local matrix at level i of the group tree.
+            currentGroup.mStackedMatrix.set(currentMatrix);
 
-            for (int i = 0; i < mGroupList.size(); i++) {
-                VGroup currentGroup = mGroupList.get(i);
-                if (currentGroup != null) {
-                    drawPath(currentGroup, canvas, w, h);
-                }
+            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+            float stackedAlpha = currentAlpha * currentGroup.mGroupAlpha;
+            drawPath(currentGroup, stackedAlpha, canvas, w, h);
+            // Draw the group tree in post order.
+            for (int i = 0 ; i < currentGroup.mChildGroupList.size(); i++) {
+                drawGroupTree(currentGroup.mChildGroupList.get(i),
+                        currentGroup.mStackedMatrix, stackedAlpha, canvas, w, h);
             }
         }
 
-        private void drawPath(VGroup vGroup, Canvas canvas, int w, int h) {
+        public void draw(Canvas canvas, int w, int h) {
+            // Travese the tree in pre-order to draw.
+            drawGroupTree(mRootGroup, IDENTITY_MATRIX, ((float) mRootAlpha) / 0xFF, canvas, w, h);
+        }
+
+        private void drawPath(VGroup vGroup, float stackedAlpha, Canvas canvas, int w, int h) {
             final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
 
-            mMatrix.reset();
-
-            // The order we apply is the same as the
-            // RenderNode.cpp::applyViewPropertyTransforms().
-            mMatrix.postTranslate(-vGroup.mPivotX, -vGroup.mPivotY);
-            mMatrix.postScale(vGroup.mScaleX, vGroup.mScaleY);
-            mMatrix.postRotate(vGroup.mRotate, 0, 0);
-            mMatrix.postTranslate(vGroup.mTranslateX + vGroup.mPivotX, vGroup.mTranslateY + vGroup.mPivotY);
-
-            mMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
-            mMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+            mFinalPathMatrix.set(vGroup.mStackedMatrix);
+            mFinalPathMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
+            mFinalPathMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
 
             ArrayList<VPath> paths = vGroup.getPaths();
             for (int i = 0; i < paths.size(); i++) {
@@ -507,45 +593,45 @@
 
                 mRenderPath.reset();
 
-                mRenderPath.addPath(path, mMatrix);
+                mRenderPath.addPath(path, mFinalPathMatrix);
 
                 if (vPath.mClip) {
                     canvas.clipPath(mRenderPath, Region.Op.REPLACE);
-                }
-
-                if (vPath.mFillColor != 0) {
-                    if (mFillPaint == null) {
-                        mFillPaint = new Paint();
-                        mFillPaint.setColorFilter(mColorFilter);
-                        mFillPaint.setStyle(Paint.Style.FILL);
-                        mFillPaint.setAntiAlias(true);
+                } else {
+                   if (vPath.mFillColor != 0) {
+                        if (mFillPaint == null) {
+                            mFillPaint = new Paint();
+                            mFillPaint.setColorFilter(mColorFilter);
+                            mFillPaint.setStyle(Paint.Style.FILL);
+                            mFillPaint.setAntiAlias(true);
+                        }
+                        mFillPaint.setColor(applyAlpha(vPath.mFillColor, stackedAlpha));
+                        canvas.drawPath(mRenderPath, mFillPaint);
                     }
 
-                    mFillPaint.setColor(vPath.mFillColor);
-                    canvas.drawPath(mRenderPath, mFillPaint);
-                }
+                    if (vPath.mStrokeColor != 0) {
+                        if (mStrokePaint == null) {
+                            mStrokePaint = new Paint();
+                            mStrokePaint.setColorFilter(mColorFilter);
+                            mStrokePaint.setStyle(Paint.Style.STROKE);
+                            mStrokePaint.setAntiAlias(true);
+                        }
 
-                if (vPath.mStrokeColor != 0) {
-                    if (mStrokePaint == null) {
-                        mStrokePaint = new Paint();
-                        mStrokePaint.setColorFilter(mColorFilter);
-                        mStrokePaint.setStyle(Paint.Style.STROKE);
-                        mStrokePaint.setAntiAlias(true);
+                        final Paint strokePaint = mStrokePaint;
+                        if (vPath.mStrokeLineJoin != null) {
+                            strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
+                        }
+
+                        if (vPath.mStrokeLineCap != null) {
+                            strokePaint.setStrokeCap(vPath.mStrokeLineCap);
+                        }
+
+                        strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+
+                        strokePaint.setColor(applyAlpha(vPath.mStrokeColor, stackedAlpha));
+                        strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+                        canvas.drawPath(mRenderPath, strokePaint);
                     }
-
-                    final Paint strokePaint = mStrokePaint;
-                    if (vPath.mStrokeLineJoin != null) {
-                        strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
-                    }
-
-                    if (vPath.mStrokeLineCap != null) {
-                        strokePaint.setStrokeCap(vPath.mStrokeLineCap);
-                    }
-
-                    strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
-                    strokePaint.setColor(vPath.mStrokeColor);
-                    strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
-                    canvas.drawPath(mRenderPath, strokePaint);
                 }
             }
         }
@@ -588,7 +674,8 @@
 
     private static class VGroup {
         private final HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
-        private final ArrayList<VPath> mVGList = new ArrayList<VPath>();
+        private final ArrayList<VPath> mPathList = new ArrayList<VPath>();
+        private final ArrayList<VGroup> mChildGroupList = new ArrayList<VGroup>();
 
         private float mRotate = 0;
         private float mPivotX = 0;
@@ -597,15 +684,36 @@
         private float mScaleY = 1;
         private float mTranslateX = 0;
         private float mTranslateY = 0;
+        private float mGroupAlpha = 1;
+
+        // mLocalMatrix is parsed from the XML.
+        private final Matrix mLocalMatrix = new Matrix();
+        // mStackedMatrix is only used when drawing, it combines all the
+        // parents' local matrices with the current one.
+        private final Matrix mStackedMatrix = new Matrix();
 
         private int[] mThemeAttrs;
 
+        private String mName = null;
+
+        public String getName() {
+            return mName;
+        }
+
+        public Matrix getLocalMatrix() {
+            return mLocalMatrix;
+        }
+
         public void add(VPath path) {
             String id = path.getID();
             mVGPathMap.put(id, path);
-            mVGList.add(path);
+            mPathList.add(path);
          }
 
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null;
+        }
+
         public void applyTheme(Theme t) {
             if (mThemeAttrs == null) {
                 return;
@@ -621,6 +729,11 @@
             mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
             mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
             mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
+            mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
+            updateLocalMatrix();
+            if (a.hasValue(R.styleable.VectorDrawableGroup_name)) {
+                mName = a.getString(R.styleable.VectorDrawableGroup_name);
+            }
             a.recycle();
         }
 
@@ -660,15 +773,34 @@
                 mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
             }
 
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_name] == 0) {
+                mName = a.getString(R.styleable.VectorDrawableGroup_name);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_alpha] == 0) {
+                mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
+            }
+
+            updateLocalMatrix();
             a.recycle();
         }
 
+        private void updateLocalMatrix() {
+            // The order we apply is the same as the
+            // RenderNode.cpp::applyViewPropertyTransforms().
+            mLocalMatrix.reset();
+            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+            mLocalMatrix.postScale(mScaleX, mScaleY);
+            mLocalMatrix.postRotate(mRotate, 0, 0);
+            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+        }
+
         /**
          * Must return in order of adding
          * @return ordered list of paths
          */
         public ArrayList<VPath> getPaths() {
-            return mVGList;
+            return mPathList;
         }
 
     }
@@ -682,7 +814,7 @@
         float mStrokeWidth = 0;
         float mStrokeOpacity = Float.NaN;
 
-        int mFillColor = 0;
+        int mFillColor = Color.BLACK;
         int mFillRule;
         float mFillOpacity = Float.NaN;
 
@@ -867,13 +999,11 @@
 
         private void updateColorAlphas() {
             if (!Float.isNaN(mFillOpacity)) {
-                mFillColor &= 0x00FFFFFF;
-                mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+                mFillColor = applyAlpha(mFillColor, mFillOpacity);
             }
 
             if (!Float.isNaN(mStrokeOpacity)) {
-                mStrokeColor &= 0x00FFFFFF;
-                mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+                mStrokeColor = applyAlpha(mStrokeColor, mStrokeOpacity);
             }
         }
 
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 442f327..e5c8898 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -71,8 +71,6 @@
 		$(LOCAL_PATH)/../../include/utils \
 		external/skia/src/core
 
-	include external/stlport/libstlport.mk
-
 	LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
 	LOCAL_CFLAGS += -Wno-unused-parameter
 	LOCAL_MODULE_CLASS := SHARED_LIBRARIES
@@ -80,16 +78,15 @@
 	LOCAL_MODULE := libhwui
 	LOCAL_MODULE_TAGS := optional
 
+	include external/stlport/libstlport.mk
+
 	ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
 		LOCAL_CFLAGS += -DANDROID_ENABLE_RENDERSCRIPT
-		LOCAL_SHARED_LIBRARIES += libRS libRScpp libstlport
+		LOCAL_SHARED_LIBRARIES += libRS libRScpp
 		LOCAL_C_INCLUDES += \
 			$(intermediates) \
 			frameworks/rs/cpp \
-			frameworks/rs \
-			external/stlport/stlport \
-			bionic/ \
-			bionic/libstdc++/include
+			frameworks/rs
 	endif
 
 	ifndef HWUI_COMPILE_SYMBOLS
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index b80f7e9..eff3011 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -63,7 +63,6 @@
 void BaseRenderNodeAnimator::setupStartValueIfNecessary(RenderNode* target, TreeInfo& info) {
     if (mPlayState == NEEDS_START) {
         setStartValue(getValue(target));
-        mPlayState = PENDING;
     }
 }
 
@@ -154,7 +153,8 @@
 }
 
 void RenderPropertyAnimator::onAttached(RenderNode* target) {
-    if (target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
+    if (mPlayState == NEEDS_START
+            && target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
         setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
     }
     (target->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 7741617..a0c7c55 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -41,6 +41,7 @@
 class BaseRenderNodeAnimator : public VirtualLightRefBase {
     PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
 public:
+    ANDROID_API void setStartValue(float value);
     ANDROID_API void setInterpolator(Interpolator* interpolator);
     ANDROID_API void setDuration(nsecs_t durationInMs);
     ANDROID_API nsecs_t duration() { return mDuration; }
@@ -64,11 +65,9 @@
     BaseRenderNodeAnimator(float finalValue);
     virtual ~BaseRenderNodeAnimator();
 
-    void setStartValue(float value);
     virtual float getValue(RenderNode* target) const = 0;
     virtual void setValue(RenderNode* target, float value) = 0;
 
-private:
     void callOnFinishedListener(TreeInfo& info);
 
     enum PlayState {
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 02f686f..9212b9de 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -788,7 +788,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
+        OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
                 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
     }
 
@@ -978,7 +978,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
+        OP_LOG("Draw patch " RECT_STRING, RECT_ARGS(mLocalBounds));
     }
 
     virtual const char* name() { return "DrawPatch"; }
@@ -1060,7 +1060,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
+        OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
     }
 
     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
@@ -1111,7 +1111,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
+        OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
     }
 
     virtual const char* name() { return "DrawRoundRect"; }
@@ -1175,7 +1175,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
+        OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
     }
 
     virtual const char* name() { return "DrawOval"; }
@@ -1195,7 +1195,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
+        OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
                 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
     }
 
@@ -1232,7 +1232,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
+        OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
     }
 
     virtual const char* name() { return "DrawPath"; }
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index b07d2c5..4b4be1b 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -16,6 +16,11 @@
 
 package android.media;
 
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * The AudioFormat class is used to access a number of audio format and
  * channel configuration constants. They are for instance used
@@ -162,4 +167,151 @@
         throw new UnsupportedOperationException("There is no valid usage of this constructor");
     }
 
+    /**
+     * Private constructor with an ignored argument to differentiate from the removed default ctor
+     * @param ignoredArgument
+     */
+    private AudioFormat(int ignoredArgument) {
+    }
+
+    /** @hide */
+    public final static int AUDIO_FORMAT_HAS_PROPERTY_NONE = 0x0;
+    /** @hide */
+    public final static int AUDIO_FORMAT_HAS_PROPERTY_ENCODING = 0x1 << 0;
+    /** @hide */
+    public final static int AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE = 0x1 << 1;
+    /** @hide */
+    public final static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK = 0x1 << 2;
+
+    private int mEncoding;
+    private int mSampleRate;
+    private int mChannelMask;
+    private int mPropertySetMask;
+
+    /**
+     * @hide CANDIDATE FOR PUBLIC API
+     * Builder class for {@link AudioFormat} objects.
+     */
+    public static class Builder {
+        private int mEncoding = ENCODING_DEFAULT;
+        private int mSampleRate = 0;
+        private int mChannelMask = CHANNEL_INVALID;
+        private int mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_NONE;
+
+        /**
+         * Constructs a new Builder with the defaults.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Constructs a new Builder from a given {@link AudioFormat}.
+         * @param af the {@link AudioFormat} object whose data will be reused in the new Builder.
+         */
+        public Builder(AudioFormat af) {
+            mEncoding = af.mEncoding;
+            mSampleRate = af.mSampleRate;
+            mChannelMask = af.mChannelMask;
+            mPropertySetMask = af.mPropertySetMask;
+        }
+
+        /**
+         * Combines all of the format characteristics that have been set and return a new
+         * {@link AudioFormat} object.
+         * @return a new {@link AudioFormat} object
+         */
+        public AudioFormat build() {
+            AudioFormat af = new AudioFormat(1980/*ignored*/);
+            af.mEncoding = mEncoding;
+            af.mSampleRate = mSampleRate;
+            af.mChannelMask = mChannelMask;
+            af.mPropertySetMask = mPropertySetMask;
+            return af;
+        }
+
+        /**
+         * Sets the data encoding format.
+         * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT},
+         *     {@link AudioFormat#ENCODING_PCM_8BIT},
+         *     {@link AudioFormat#ENCODING_PCM_16BIT},
+         *     {@link AudioFormat#ENCODING_PCM_FLOAT}.
+         * @return the same Builder instance.
+         * @throws java.lang.IllegalArgumentException
+         */
+        public Builder setEncoding(@Encoding int encoding) throws IllegalArgumentException {
+            switch (encoding) {
+                case ENCODING_DEFAULT:
+                    mEncoding = ENCODING_PCM_16BIT;
+                    break;
+                case ENCODING_PCM_8BIT:
+                case ENCODING_PCM_16BIT:
+                case ENCODING_PCM_FLOAT:
+                    mEncoding = encoding;
+                    break;
+                case ENCODING_INVALID:
+                default:
+                    throw new IllegalArgumentException("Invalid encoding " + encoding);
+            }
+            mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_ENCODING;
+            return this;
+        }
+
+        /**
+         * Sets the channel mask.
+         * @param channelMask describes the configuration of the audio channels.
+         *    <p>For output, the mask should be a combination of
+         *    {@link AudioFormat#CHANNEL_OUT_FRONT_LEFT},
+         *    {@link AudioFormat#CHANNEL_OUT_FRONT_CENTER},
+         *    {@link AudioFormat#CHANNEL_OUT_FRONT_RIGHT},
+         *    {@link AudioFormat#CHANNEL_OUT_SIDE_LEFT},
+         *    {@link AudioFormat#CHANNEL_OUT_SIDE_RIGHT},
+         *    {@link AudioFormat#CHANNEL_OUT_BACK_LEFT},
+         *    {@link AudioFormat#CHANNEL_OUT_BACK_RIGHT}.
+         *    <p>for input, the mask should be {@link AudioFormat#CHANNEL_IN_MONO} or
+         *    {@link AudioFormat#CHANNEL_IN_STEREO}.  {@link AudioFormat#CHANNEL_IN_MONO} is
+         *    guaranteed to work on all devices.
+         * @return the same Builder instance.
+         */
+        public Builder setChannelMask(int channelMask) {
+            // only validated when used, with input or output context
+            mChannelMask = channelMask;
+            mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK;
+            return this;
+        }
+
+        /**
+         * Sets the sample rate.
+         * @param sampleRate the sample rate expressed in Hz
+         * @return the same Builder instance.
+         * @throws java.lang.IllegalArgumentException
+         */
+        public Builder setSampleRate(int sampleRate) throws IllegalArgumentException {
+            if ((sampleRate <= 0) || (sampleRate > 192000)) {
+                throw new IllegalArgumentException("Invalid sample rate " + sampleRate);
+            }
+            mSampleRate = sampleRate;
+            mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE;
+            return this;
+        }
+    }
+
+    @Override
+    public String toString () {
+        return new String("AudioFormat:"
+                + " props=" + mPropertySetMask
+                + " enc=" + mEncoding
+                + " chan=0x" + Integer.toHexString(mChannelMask)
+                + " rate=" + mSampleRate);
+    }
+
+    /** @hide */
+    @IntDef({
+        ENCODING_DEFAULT,
+        ENCODING_PCM_8BIT,
+        ENCODING_PCM_16BIT,
+        ENCODING_PCM_FLOAT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Encoding {}
+
 }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a0ff074..84d4ab6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -644,7 +644,12 @@
             if (mUseMasterVolume) {
                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
             } else {
-                service.adjustVolume(direction, flags, mContext.getOpPackageName());
+                if (USE_SESSIONS) {
+                    MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
+                    helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
+                } else {
+                    service.adjustVolume(direction, flags, mContext.getOpPackageName());
+                }
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in adjustVolume", e);
@@ -674,8 +679,13 @@
             if (mUseMasterVolume) {
                 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
             } else {
-                service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags,
-                        mContext.getOpPackageName());
+                if (USE_SESSIONS) {
+                    MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
+                    helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
+                } else {
+                    service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags,
+                            mContext.getOpPackageName());
+                }
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e);
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index cd9a4de..782ecd8 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -49,73 +49,77 @@
         // find the looper for our new event handler
         Looper looper = Looper.myLooper();
         if (looper == null) {
-            throw new IllegalArgumentException("Calling thread not associated with a looper");
+            looper = Looper.getMainLooper();
         }
 
-        mHandler = new Handler(looper) {
-            @Override
-            public void handleMessage(Message msg) {
-                Log.i(TAG, "handleMessage: "+msg.what);
-                ArrayList<AudioManager.OnAudioPortUpdateListener> listeners;
-                synchronized (this) {
-                    if (msg.what == AUDIOPORT_EVENT_NEW_LISTENER) {
-                        listeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
-                        if (mListeners.contains(msg.obj)) {
-                            listeners.add((AudioManager.OnAudioPortUpdateListener)msg.obj);
+        if (looper != null) {
+            mHandler = new Handler(looper) {
+                @Override
+                public void handleMessage(Message msg) {
+                    Log.i(TAG, "handleMessage: "+msg.what);
+                    ArrayList<AudioManager.OnAudioPortUpdateListener> listeners;
+                    synchronized (this) {
+                        if (msg.what == AUDIOPORT_EVENT_NEW_LISTENER) {
+                            listeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
+                            if (mListeners.contains(msg.obj)) {
+                                listeners.add((AudioManager.OnAudioPortUpdateListener)msg.obj);
+                            }
+                        } else {
+                            listeners = mListeners;
                         }
-                    } else {
-                        listeners = mListeners;
                     }
-                }
-                if (listeners.isEmpty()) {
-                    return;
-                }
-                // reset audio port cache if the event corresponds to a change coming
-                // from audio policy service or if mediaserver process died.
-                if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED ||
-                        msg.what == AUDIOPORT_EVENT_PATCH_LIST_UPDATED ||
-                        msg.what == AUDIOPORT_EVENT_SERVICE_DIED) {
-                    mAudioManager.resetAudioPortGeneration();
-                }
-                ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
-                ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
-                if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
-                    int status = mAudioManager.updateAudioPortCache(ports, patches);
-                    if (status != AudioManager.SUCCESS) {
+                    if (listeners.isEmpty()) {
                         return;
                     }
-                }
-
-                switch (msg.what) {
-                case AUDIOPORT_EVENT_NEW_LISTENER:
-                case AUDIOPORT_EVENT_PORT_LIST_UPDATED:
-                    AudioPort[] portList = ports.toArray(new AudioPort[0]);
-                    for (int i = 0; i < listeners.size(); i++) {
-                        listeners.get(i).OnAudioPortListUpdate(portList);
+                    // reset audio port cache if the event corresponds to a change coming
+                    // from audio policy service or if mediaserver process died.
+                    if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED ||
+                            msg.what == AUDIOPORT_EVENT_PATCH_LIST_UPDATED ||
+                            msg.what == AUDIOPORT_EVENT_SERVICE_DIED) {
+                        mAudioManager.resetAudioPortGeneration();
                     }
-                    if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED) {
+                    ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
+                    ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
+                    if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
+                        int status = mAudioManager.updateAudioPortCache(ports, patches);
+                        if (status != AudioManager.SUCCESS) {
+                            return;
+                        }
+                    }
+
+                    switch (msg.what) {
+                    case AUDIOPORT_EVENT_NEW_LISTENER:
+                    case AUDIOPORT_EVENT_PORT_LIST_UPDATED:
+                        AudioPort[] portList = ports.toArray(new AudioPort[0]);
+                        for (int i = 0; i < listeners.size(); i++) {
+                            listeners.get(i).OnAudioPortListUpdate(portList);
+                        }
+                        if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED) {
+                            break;
+                        }
+                        // FALL THROUGH
+
+                    case AUDIOPORT_EVENT_PATCH_LIST_UPDATED:
+                        AudioPatch[] patchList = patches.toArray(new AudioPatch[0]);
+                        for (int i = 0; i < listeners.size(); i++) {
+                            listeners.get(i).OnAudioPatchListUpdate(patchList);
+                        }
+                        break;
+
+                    case AUDIOPORT_EVENT_SERVICE_DIED:
+                        for (int i = 0; i < listeners.size(); i++) {
+                            listeners.get(i).OnServiceDied();
+                        }
+                        break;
+
+                    default:
                         break;
                     }
-                    // FALL THROUGH
-
-                case AUDIOPORT_EVENT_PATCH_LIST_UPDATED:
-                    AudioPatch[] patchList = patches.toArray(new AudioPatch[0]);
-                    for (int i = 0; i < listeners.size(); i++) {
-                        listeners.get(i).OnAudioPatchListUpdate(patchList);
-                    }
-                    break;
-
-                case AUDIOPORT_EVENT_SERVICE_DIED:
-                    for (int i = 0; i < listeners.size(); i++) {
-                        listeners.get(i).OnServiceDied();
-                    }
-                    break;
-
-                default:
-                    break;
                 }
-            }
-        };
+            };
+        } else {
+            mHandler = null;
+        }
 
         native_setup(new WeakReference<AudioPortEventHandler>(this));
     }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 8eb83e4..cfd9c3b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -816,6 +816,8 @@
     *         with the estimated time when that frame was presented or is committed to
     *         be presented.
     *         In the case that no timestamp is available, any supplied instance is left unaltered.
+    *         A timestamp may be temporarily unavailable while the audio clock is stabilizing,
+    *         or during and immediately after a route change.
     */
     // Add this text when the "on new timestamp" API is added:
     //   Use if you need to get the most recent timestamp outside of the event callback handler.
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index c4233c3..1cfc5bc 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -47,4 +47,8 @@
     void setMetadata(in MediaMetadata metadata);
     void setPlaybackState(in PlaybackState state);
     void setRatingType(int type);
+
+    // These commands relate to volume handling
+    void configureVolumeHandling(int type, int arg1, int arg2);
+    void setCurrentVolume(int currentVolume);
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 103c3f1..0316d1fa 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -45,4 +45,8 @@
     void onRewind();
     void onSeekTo(long pos);
     void onRate(in Rating rating);
+
+    // These callbacks are for volume handling
+    void onAdjustVolumeBy(int delta);
+    void onSetVolumeTo(int value);
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 38b92932..6d9888f 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -29,4 +29,5 @@
     ISession createSession(String packageName, in ISessionCallback cb, String tag, int userId);
     List<IBinder> getSessions(in ComponentName compName, int userId);
     void dispatchMediaKeyEvent(in KeyEvent keyEvent, boolean needWakeLock);
+    void dispatchAdjustVolumeBy(int suggestedStream, int delta, int flags);
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 90ccf68..7972639 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -124,9 +124,21 @@
      */
     public static final int DISCONNECT_REASON_SESSION_DESTROYED = 5;
 
-    private static final String KEY_COMMAND = "command";
-    private static final String KEY_EXTRAS = "extras";
-    private static final String KEY_CALLBACK = "callback";
+    /**
+     * The session uses local playback. Used for configuring volume handling
+     * with the system.
+     *
+     * @hide
+     */
+    public static final int VOLUME_TYPE_LOCAL = 1;
+
+    /**
+     * The session uses remote playback. Used for configuring volume handling
+     * with the system.
+     *
+     * @hide
+     */
+    public static final int VOLUME_TYPE_REMOTE = 2;
 
     private final Object mLock = new Object();
 
@@ -143,6 +155,7 @@
             = new ArrayMap<String, RouteInterface.EventListener>();
 
     private Route mRoute;
+    private RemoteVolumeProvider mVolumeProvider;
 
     private boolean mActive = false;;
 
@@ -242,7 +255,11 @@
      * @param stream The {@link AudioManager} stream this session is playing on.
      */
     public void setPlaybackToLocal(int stream) {
-        // TODO
+        try {
+            mBinder.configureVolumeHandling(VOLUME_TYPE_LOCAL, stream, 0);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Failure in setPlaybackToLocal.", e);
+        }
     }
 
     /**
@@ -259,7 +276,14 @@
         if (volumeProvider == null) {
             throw new IllegalArgumentException("volumeProvider may not be null!");
         }
-        // TODO
+        mVolumeProvider = volumeProvider;
+
+        try {
+            mBinder.configureVolumeHandling(VOLUME_TYPE_REMOTE, volumeProvider.getVolumeControl(),
+                    volumeProvider.getMaxVolume());
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Failure in setPlaybackToRemote.", e);
+        }
     }
 
     /**
@@ -942,6 +966,26 @@
 
         }
 
+        /*
+         * (non-Javadoc)
+         * @see android.media.session.ISessionCallback#onAdjustVolumeBy(int)
+         */
+        @Override
+        public void onAdjustVolumeBy(int delta) throws RemoteException {
+            // TODO(epastern): Auto-generated method stub
+
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see android.media.session.ISessionCallback#onSetVolumeTo(int)
+         */
+        @Override
+        public void onSetVolumeTo(int value) throws RemoteException {
+            // TODO(epastern): Auto-generated method stub
+
+        }
+
     }
 
     private class CallbackMessageHandler extends Handler {
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index c303e77..099f601 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -76,6 +76,13 @@
         }
     }
 
+    public void sendAdjustVolumeBy(int suggestedStream, int delta, int flags) {
+        mSessionManager.dispatchAdjustVolumeBy(suggestedStream, delta, flags);
+        if (DEBUG) {
+            Log.d(TAG, "dispatched volume adjustment");
+        }
+    }
+
     public void addRccListener(PendingIntent pi,
             MediaSession.TransportControlsCallback listener) {
         if (pi == null) {
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 8d5e338..9e8b0d3 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -166,4 +166,22 @@
             Log.e(TAG, "Failed to send key event.", e);
         }
     }
+
+    /**
+     * Dispatch an adjust volume request to the system. It will be routed to the
+     * most relevant stream/session.
+     *
+     * @param suggestedStream The stream to fall back to if there isn't a
+     *            relevant stream
+     * @param delta The amount to adjust the volume by.
+     * @param flags Any flags to include with the volume change.
+     * @hide
+     */
+    public void dispatchAdjustVolumeBy(int suggestedStream, int delta, int flags) {
+        try {
+            mService.dispatchAdjustVolumeBy(suggestedStream, delta, flags);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send adjust volume.", e);
+        }
+    }
 }
diff --git a/core/java/android/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
similarity index 94%
rename from core/java/android/tv/ITvInputClient.aidl
rename to media/java/android/media/tv/ITvInputClient.aidl
index ef89c68..dc79a73 100644
--- a/core/java/android/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.content.ComponentName;
+import android.media.tv.ITvInputSession;
 import android.os.Bundle;
-import android.tv.ITvInputSession;
 import android.view.InputChannel;
 
 /**
diff --git a/core/java/android/tv/ITvInputHardware.aidl b/media/java/android/media/tv/ITvInputHardware.aidl
similarity index 95%
rename from core/java/android/tv/ITvInputHardware.aidl
rename to media/java/android/media/tv/ITvInputHardware.aidl
index 7250453..f35e8f3 100644
--- a/core/java/android/tv/ITvInputHardware.aidl
+++ b/media/java/android/media/tv/ITvInputHardware.aidl
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
-import android.tv.TvStreamConfig;
+import android.media.tv.TvStreamConfig;
 import android.view.KeyEvent;
 import android.view.Surface;
 
diff --git a/core/java/android/tv/ITvInputHardwareCallback.aidl b/media/java/android/media/tv/ITvInputHardwareCallback.aidl
similarity index 91%
rename from core/java/android/tv/ITvInputHardwareCallback.aidl
rename to media/java/android/media/tv/ITvInputHardwareCallback.aidl
index 83041be..870883b 100644
--- a/core/java/android/tv/ITvInputHardwareCallback.aidl
+++ b/media/java/android/media/tv/ITvInputHardwareCallback.aidl
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
-import android.tv.TvStreamConfig;
+import android.media.tv.TvStreamConfig;
 
 /**
  * @hide
diff --git a/core/java/android/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
similarity index 89%
rename from core/java/android/tv/ITvInputManager.aidl
rename to media/java/android/media/tv/ITvInputManager.aidl
index c6f8d79..6db5a18 100644
--- a/core/java/android/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.content.ComponentName;
 import android.graphics.Rect;
+import android.media.tv.ITvInputHardware;
+import android.media.tv.ITvInputHardwareCallback;
+import android.media.tv.ITvInputClient;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvInputInfo;
 import android.net.Uri;
-import android.tv.ITvInputHardware;
-import android.tv.ITvInputHardwareCallback;
-import android.tv.ITvInputClient;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvInputInfo;
 import android.view.Surface;
 
 /**
diff --git a/core/java/android/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
similarity index 88%
rename from core/java/android/tv/ITvInputService.aidl
rename to media/java/android/media/tv/ITvInputService.aidl
index 4f1bc2b..992e424 100644
--- a/core/java/android/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
-import android.tv.ITvInputServiceCallback;
-import android.tv.ITvInputSessionCallback;
+import android.media.tv.ITvInputServiceCallback;
+import android.media.tv.ITvInputSessionCallback;
 import android.view.InputChannel;
 
 /**
diff --git a/core/java/android/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
similarity index 96%
rename from core/java/android/tv/ITvInputServiceCallback.aidl
rename to media/java/android/media/tv/ITvInputServiceCallback.aidl
index 71fc780..c9484dd 100644
--- a/core/java/android/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.content.ComponentName;
 
diff --git a/core/java/android/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
similarity index 97%
rename from core/java/android/tv/ITvInputSession.aidl
rename to media/java/android/media/tv/ITvInputSession.aidl
index 32fee4b..fb2e251 100644
--- a/core/java/android/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.graphics.Rect;
 import android.net.Uri;
diff --git a/core/java/android/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
similarity index 93%
rename from core/java/android/tv/ITvInputSessionCallback.aidl
rename to media/java/android/media/tv/ITvInputSessionCallback.aidl
index e27b8bf..71f2d07 100644
--- a/core/java/android/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
+import android.media.tv.ITvInputSession;
 import android.os.Bundle;
-import android.tv.ITvInputSession;
 
 /**
  * Helper interface for ITvInputSession to allow the TV input to notify the system service when a
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
similarity index 96%
rename from core/java/android/tv/ITvInputSessionWrapper.java
rename to media/java/android/media/tv/ITvInputSessionWrapper.java
index 3ccccf3..975e391 100644
--- a/core/java/android/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -14,22 +14,20 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.media.tv.TvInputManager.Session;
+import android.media.tv.TvInputService.TvInputSessionImpl;
 import android.net.Uri;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.tv.TvInputManager.Session;
-import android.tv.TvInputService.TvInputSessionImpl;
 import android.util.Log;
 import android.view.InputChannel;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.view.Surface;
 
 import com.android.internal.os.HandlerCaller;
diff --git a/core/java/android/provider/TvContract.java b/media/java/android/media/tv/TvContract.java
similarity index 82%
rename from core/java/android/provider/TvContract.java
rename to media/java/android/media/tv/TvContract.java
index 0d90a16..6e0586e 100644
--- a/core/java/android/provider/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package android.provider;
+package android.media.tv;
 
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.net.Uri;
-import android.tv.TvInputService;
+import android.provider.BaseColumns;
 
 import java.util.List;
 
@@ -45,7 +45,7 @@
  */
 public final class TvContract {
     /** The authority for the TV provider. */
-    public static final String AUTHORITY = "com.android.tv";
+    public static final String AUTHORITY = "android.media.tv";
 
     private static final String PATH_CHANNEL = "channel";
     private static final String PATH_PROGRAM = "program";
@@ -88,8 +88,8 @@
     /**
      * Builds a URI that points to all browsable channels from a given TV input.
      *
-     * @param name {@link ComponentName} of the {@link android.tv.TvInputService} that implements
-     *            the given TV input.
+     * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
+     *            implements the given TV input.
      */
     public static final Uri buildChannelsUriForInput(ComponentName name) {
         return buildChannelsUriForInput(name, true);
@@ -98,8 +98,8 @@
     /**
      * Builds a URI that points to all or browsable-only channels from a given TV input.
      *
-     * @param name {@link ComponentName} of the {@link android.tv.TvInputService} that implements
-     *            the given TV input.
+     * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
+     *            implements the given TV input.
      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
      *            to {@code false} the URI points to all channels regardless of whether they are
      *            browsable or not.
@@ -243,12 +243,10 @@
                 + PATH_CHANNEL);
 
         /** The MIME type of a directory of TV channels. */
-        public static final String CONTENT_TYPE =
-                "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
 
         /** The MIME type of a single TV channel. */
-        public static final String CONTENT_ITEM_TYPE =
-                "vnd.android.cursor.item/vnd.com.android.tv.channels";
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
 
         /** A generic channel type. */
         public static final int TYPE_OTHER = 0x0;
@@ -319,11 +317,11 @@
         /** A generic service type. */
         public static final int SERVICE_TYPE_OTHER = 0x0;
 
-        /** The service type for regular TV channels. */
-        public static final int SERVICE_TYPE_TV = 0x1;
+        /** The service type for regular TV channels that have both audio and video. */
+        public static final int SERVICE_TYPE_AUDIO_VIDEO = 0x1;
 
-        /** The service type for radio channels. */
-        public static final int SERVICE_TYPE_RADIO = 0x2;
+        /** The service type for radio channels that have audio only. */
+        public static final int SERVICE_TYPE_AUDIO = 0x2;
 
         /**
          * The name of the {@link TvInputService} subclass that provides this TV channel. This
@@ -363,7 +361,7 @@
          * a radio-like channel. Use the same coding for {@code service_type} in the underlying
          * broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB
          * STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER},
-         * {@link #SERVICE_TYPE_TV}, {@link #SERVICE_TYPE_RADIO}
+         * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO}
          * </p><p>
          * This is a required field.
          * </p><p>
@@ -376,7 +374,7 @@
          * The original network ID of this TV channel.
          * <p>
          * This is used to identify the originating delivery system, if applicable. Use the same
-         * coding for {@code origianal_network_id} in the underlying broadcast standard if it is
+         * coding for {@code original_network_id} in the underlying broadcast standard if it is
          * defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be
          * globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID},
          * {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a
@@ -496,17 +494,20 @@
          * </p><p>
          * Type: INTEGER (boolean)
          * </p>
+         * @hide
          */
         public static final String COLUMN_LOCKED = "locked";
 
         /**
-         * Generic data used by individual TV input services.
+         * Internal data used by individual TV input services.
          * <p>
+         * This is internal to the provider that inserted it, and should not be decoded by other
+         * apps.
+         * </p><p>
          * Type: BLOB
          * </p>
          */
-        public static final String COLUMN_DATA = "data";
-
+        public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
 
         /**
          * The version number of this row entry used by TV input services.
@@ -532,12 +533,10 @@
                 + PATH_PROGRAM);
 
         /** The MIME type of a directory of TV programs. */
-        public static final String CONTENT_TYPE =
-                "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program";
 
         /** The MIME type of a single TV program. */
-        public static final String CONTENT_ITEM_TYPE =
-                "vnd.android.cursor.item/vnd.com.android.tv.programs";
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
 
         /**
          * The ID of the TV channel that contains this TV program.
@@ -578,44 +577,42 @@
          * <p>
          * Use the same language appeared in the underlying broadcast standard, if applicable. (For
          * example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
-         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, use one of the
-         * following genres:
-         * <ul>
-         *     <li>Family/Kids</li>
-         *     <li>Sports</li>
-         *     <li>Shopping</li>
-         *     <li>Movies</li>
-         *     <li>Comedy</li>
-         *     <li>Travel</li>
-         *     <li>Drama</li>
-         *     <li>Education</li>
-         *     <li>Animal/Wildlife</li>
-         *     <li>News</li>
-         *     <li>Gaming</li>
-         *     <li>Others</li>
-         * </ul>
+         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty.
          * </p><p>
          * Type: TEXT
          * </p>
          */
-        public static final String COLUMN_GENRE = "genre";
+        public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
 
         /**
-         * The description of this TV program that is displayed to the user by default.
+         * The comma-separated canonical genre string of this TV program.
          * <p>
-         * The maximum length of this field is 256 characters.
+         * Canonical genres are defined in {@link Genres}. Use {@link Genres#encode Genres.encode()}
+         * to create a text that can be stored in this column. Use {@link Genres#decode
+         * Genres.decode()} to get the canonical genre strings from the text stored in this column.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         * @see Genres
+         */
+        public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
+
+        /**
+         * The short description of this TV program that is displayed to the user by default.
+         * <p>
+         * It is recommended to limit the length of the descriptions to 256 characters.
          * </p><p>
          * Type: TEXT
          * </p>
          */
-        public static final String COLUMN_DESCRIPTION = "description";
+        public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
 
         /**
          * The detailed, lengthy description of this TV program that is displayed only when the user
          * wants to see more information.
          * <p>
-         * TV input services should leave this field empty if they have no additional
-         * details beyond {@link #COLUMN_DESCRIPTION}.
+         * TV input services should leave this field empty if they have no additional details beyond
+         * {@link #COLUMN_SHORT_DESCRIPTION}.
          * </p><p>
          * Type: TEXT
          * </p>
@@ -634,12 +631,15 @@
         public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
 
         /**
-         * Generic data used by TV input services.
+         * Internal data used by individual TV input services.
          * <p>
+         * This is internal to the provider that inserted it, and should not be decoded by other
+         * apps.
+         * </p><p>
          * Type: BLOB
          * </p>
          */
-        public static final String COLUMN_DATA = "data";
+        public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
 
         /**
          * The version number of this row entry used by TV input services.
@@ -655,6 +655,72 @@
         public static final String COLUMN_VERSION_NUMBER = "version_number";
 
         private Programs() {}
+
+        /** Canonical genres for TV programs. */
+        public static final class Genres {
+            /** The genre for Family/Kids. */
+            public static final String FAMILY_KIDS = "Family/Kids";
+
+            /** The genre for Sports. */
+            public static final String SPORTS = "Sports";
+
+            /** The genre for Shopping. */
+            public static final String SHOPPING = "Shopping";
+
+            /** The genre for Movies. */
+            public static final String MOVIES = "Movies";
+
+            /** The genre for Comedy. */
+            public static final String COMEDY = "Comedy";
+
+            /** The genre for Travel. */
+            public static final String TRAVEL = "Travel";
+
+            /** The genre for Drama. */
+            public static final String DRAMA = "Drama";
+
+            /** The genre for Education. */
+            public static final String EDUCATION = "Education";
+
+            /** The genre for Animal/Wildlife. */
+            public static final String ANIMAL_WILDLIFE = "Animal/Wildlife";
+
+            /** The genre for News. */
+            public static final String NEWS = "News";
+
+            /** The genre for Gaming. */
+            public static final String GAMING = "Gaming";
+
+            private Genres() {}
+
+            /**
+             * Encodes canonical genre strings to a text that can be put into the database.
+             *
+             * @param genres Canonical genre strings. Use the strings defined in this class.
+             * @return an encoded genre string that can be inserted into the
+             *         {@link #COLUMN_CANONICAL_GENRE} column.
+             */
+            public static String encode(String... genres) {
+                StringBuilder sb = new StringBuilder();
+                String separator = "";
+                for (String genre : genres) {
+                    sb.append(separator).append(genre);
+                    separator = ",";
+                }
+                return sb.toString();
+            }
+
+            /**
+             * Decodes the canonical genre strings from the text stored in the database.
+             *
+             * @param genres The encoded genre string retrieved from the
+             *            {@link #COLUMN_CANONICAL_GENRE} column.
+             * @return canonical genre strings.
+             */
+            public static String[] decode(String genres) {
+                return genres.split("\\s*,\\s*");
+            }
+        }
     }
 
     /**
@@ -670,12 +736,10 @@
                 Uri.parse("content://" + AUTHORITY + "/watched_program");
 
         /** The MIME type of a directory of watched programs. */
-        public static final String CONTENT_TYPE =
-                "vnd.android.cursor.dir/vnd.com.android.tv.watched_programs";
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program";
 
         /** The MIME type of a single item in this table. */
-        public static final String CONTENT_ITEM_TYPE =
-                "vnd.android.cursor.item/vnd.com.android.tv.watched_programs";
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program";
 
         /**
          * The UTC time that the user started watching this TV program, in milliseconds since the
diff --git a/core/java/android/tv/TvInputHardwareInfo.aidl b/media/java/android/media/tv/TvInputHardwareInfo.aidl
similarity index 95%
rename from core/java/android/tv/TvInputHardwareInfo.aidl
rename to media/java/android/media/tv/TvInputHardwareInfo.aidl
index 484ab60..a4c38bb 100644
--- a/core/java/android/tv/TvInputHardwareInfo.aidl
+++ b/media/java/android/media/tv/TvInputHardwareInfo.aidl
@@ -15,6 +15,6 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 parcelable TvInputHardwareInfo;
diff --git a/core/java/android/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java
similarity index 98%
rename from core/java/android/tv/TvInputHardwareInfo.java
rename to media/java/android/media/tv/TvInputHardwareInfo.java
index b0dc58e..4beb960 100644
--- a/core/java/android/tv/TvInputHardwareInfo.java
+++ b/media/java/android/media/tv/TvInputHardwareInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.os.Parcel;
 import android.os.Parcelable;
diff --git a/core/java/android/tv/TvInputInfo.aidl b/media/java/android/media/tv/TvInputInfo.aidl
similarity index 95%
rename from core/java/android/tv/TvInputInfo.aidl
rename to media/java/android/media/tv/TvInputInfo.aidl
index abc4b47..ba139a2 100644
--- a/core/java/android/tv/TvInputInfo.aidl
+++ b/media/java/android/media/tv/TvInputInfo.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 parcelable TvInputInfo;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
new file mode 100644
index 0000000..ed599ed
--- /dev/null
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * This class is used to specify meta information of a TV input.
+ */
+public final class TvInputInfo implements Parcelable {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "TvInputInfo";
+
+    /**
+     * The name of the TV input service to provide to the setup activity and settings activity.
+     */
+    public static final String EXTRA_SERVICE_NAME = "serviceName";
+
+    private static final String XML_START_TAG_NAME = "tv-input";
+
+    private final ResolveInfo mService;
+    private final String mId;
+
+    // Attributes from XML meta data.
+    private String mSetupActivity;
+    private String mSettingsActivity;
+
+    /**
+     * Create a new instance of the TvInputInfo class,
+     * instantiating it from the given Context and ResolveInfo.
+     *
+     * @param service The ResolveInfo returned from the package manager about this TV input service.
+     * @hide */
+    public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service)
+            throws XmlPullParserException, IOException {
+        ServiceInfo si = service.serviceInfo;
+        PackageManager pm = context.getPackageManager();
+        XmlResourceParser parser = null;
+        try {
+            parser = si.loadXmlMetaData(pm, TvInputService.SERVICE_META_DATA);
+            if (parser == null) {
+                throw new XmlPullParserException("No " + TvInputService.SERVICE_META_DATA
+                        + " meta-data for " + si.name);
+            }
+
+            Resources res = pm.getResourcesForApplication(si.applicationInfo);
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+            }
+
+            String nodeName = parser.getName();
+            if (!XML_START_TAG_NAME.equals(nodeName)) {
+                throw new XmlPullParserException(
+                        "Meta-data does not start with tv-input-service tag in " + si.name);
+            }
+
+            TvInputInfo input = new TvInputInfo(context, service);
+            TypedArray sa = res.obtainAttributes(attrs,
+                    com.android.internal.R.styleable.TvInputService);
+            input.mSetupActivity = sa.getString(
+                    com.android.internal.R.styleable.TvInputService_setupActivity);
+            if (DEBUG) {
+                Log.d(TAG, "Setup activity loaded. [" + input.mSetupActivity + "] for " + si.name);
+            }
+            input.mSettingsActivity = sa.getString(
+                    com.android.internal.R.styleable.TvInputService_settingsActivity);
+            if (DEBUG) {
+                Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
+                        + si.name);
+            }
+            sa.recycle();
+
+            return input;
+        } catch (NameNotFoundException e) {
+            throw new XmlPullParserException("Unable to create context for: " + si.packageName);
+        } finally {
+            if (parser != null) {
+                parser.close();
+            }
+        }
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param service The ResolveInfo returned from the package manager about this TV input service.
+     * @hide
+     */
+    private TvInputInfo(Context context, ResolveInfo service) {
+        mService = service;
+        ServiceInfo si = service.serviceInfo;
+        mId = generateInputIdForComponentName(new ComponentName(si.packageName, si.name));
+    }
+
+    /**
+     * Returns a unique ID for this TV input. The ID is generated from the package and class name
+     * implementing the TV input service.
+     */
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the .apk package that implements this TV input service.
+     */
+    public String getPackageName() {
+        return mService.serviceInfo.packageName;
+    }
+
+    /**
+     * Returns the class name of the service component that implements this TV input service.
+     */
+    public String getServiceName() {
+        return mService.serviceInfo.name;
+    }
+
+    /**
+     * Returns the component of the service that implements this TV input.
+     */
+    public ComponentName getComponent() {
+        return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
+    }
+
+    /**
+     * Returns an intent to start the setup activity for this TV input service.
+     */
+    public Intent getIntentForSetupActivity() {
+        if (!TextUtils.isEmpty(mSetupActivity)) {
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setClassName(getPackageName(), mSetupActivity);
+            intent.putExtra(EXTRA_SERVICE_NAME, getServiceName());
+            return intent;
+        }
+        return null;
+    }
+
+    /**
+     * Returns an intent to start the settings activity for this TV input service.
+     */
+    public Intent getIntentForSettingsActivity() {
+        if (!TextUtils.isEmpty(mSettingsActivity)) {
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setClassName(getPackageName(), mSettingsActivity);
+            intent.putExtra(EXTRA_SERVICE_NAME, getServiceName());
+            return intent;
+        }
+        return null;
+    }
+
+    /**
+     * Loads the user-displayed label for this TV input service.
+     *
+     * @param pm Supplies a PackageManager used to load the TV input's resources.
+     * @return a CharSequence containing the TV input's label. If the TV input does not have
+     *         a label, its name is returned.
+     */
+    public CharSequence loadLabel(PackageManager pm) {
+        return mService.loadLabel(pm);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        return mId.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+
+        if (!(o instanceof TvInputInfo)) {
+            return false;
+        }
+
+        TvInputInfo obj = (TvInputInfo) o;
+        return mId.equals(obj.mId)
+                && mService.serviceInfo.packageName.equals(obj.mService.serviceInfo.packageName)
+                && mService.serviceInfo.name.equals(obj.mService.serviceInfo.name);
+    }
+
+    @Override
+    public String toString() {
+        return "TvInputInfo{id=" + mId
+                + ", pkg=" + mService.serviceInfo.packageName
+                + ", service=" + mService.serviceInfo.name + "}";
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        mService.writeToParcel(dest, flags);
+        dest.writeString(mSetupActivity);
+        dest.writeString(mSettingsActivity);
+    }
+
+    /**
+     * Used to generate an input id from a ComponentName.
+     *
+     * @param name the component name for generating an input id.
+     * @return the generated input id for the given {@code name}.
+     * @hide
+     */
+    public static final String generateInputIdForComponentName(ComponentName name) {
+        return name.flattenToShortString();
+    }
+
+    /**
+     * Used to make this class parcelable.
+     *
+     * @hide
+     */
+    public static final Parcelable.Creator<TvInputInfo> CREATOR =
+            new Parcelable.Creator<TvInputInfo>() {
+        @Override
+        public TvInputInfo createFromParcel(Parcel in) {
+            return new TvInputInfo(in);
+        }
+
+        @Override
+        public TvInputInfo[] newArray(int size) {
+            return new TvInputInfo[size];
+        }
+    };
+
+    private TvInputInfo(Parcel in) {
+        mId = in.readString();
+        mService = ResolveInfo.CREATOR.createFromParcel(in);
+        mSetupActivity = in.readString();
+        mSettingsActivity = in.readString();
+    }
+}
diff --git a/core/java/android/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
similarity index 99%
rename from core/java/android/tv/TvInputManager.java
rename to media/java/android/media/tv/TvInputManager.java
index d0c2ca6..1335a1b 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.graphics.Rect;
 import android.net.Uri;
diff --git a/core/java/android/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
similarity index 97%
rename from core/java/android/tv/TvInputService.java
rename to media/java/android/media/tv/TvInputService.java
index 03d24db..3213019 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.app.Service;
 import android.content.ComponentName;
@@ -22,6 +22,8 @@
 import android.content.Intent;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.media.tv.ITvInputService;
+import android.media.tv.TvInputManager.Session;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -29,7 +31,6 @@
 import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.tv.TvInputManager.Session;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.InputChannel;
@@ -59,7 +60,15 @@
      * must also require the {@link android.Manifest.permission#BIND_TV_INPUT} permission so that
      * other applications cannot abuse it.
      */
-    public static final String SERVICE_INTERFACE = "android.tv.TvInputService";
+    public static final String SERVICE_INTERFACE = "android.media.tv.TvInputService";
+
+    /**
+     * Name under which a TvInputService component publishes information about itself.
+     * This meta-data must reference an XML resource containing an
+     * <code>&lt;{@link android.R.styleable#TvInputService tv-input}&gt;</code>
+     * tag.
+     */
+    public static final String SERVICE_META_DATA = "android.media.tv.input";
 
     private String mId;
     private final Handler mHandler = new ServiceHandler();
diff --git a/core/java/android/tv/TvStreamConfig.aidl b/media/java/android/media/tv/TvStreamConfig.aidl
similarity index 95%
rename from core/java/android/tv/TvStreamConfig.aidl
rename to media/java/android/media/tv/TvStreamConfig.aidl
index 4d0add4..569fcc0 100644
--- a/core/java/android/tv/TvStreamConfig.aidl
+++ b/media/java/android/media/tv/TvStreamConfig.aidl
@@ -15,6 +15,6 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 parcelable TvStreamConfig;
\ No newline at end of file
diff --git a/core/java/android/tv/TvStreamConfig.java b/media/java/android/media/tv/TvStreamConfig.java
similarity index 98%
rename from core/java/android/tv/TvStreamConfig.java
rename to media/java/android/media/tv/TvStreamConfig.java
index 03e63b1..7f0c92f 100644
--- a/core/java/android/tv/TvStreamConfig.java
+++ b/media/java/android/media/tv/TvStreamConfig.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.os.Parcel;
 import android.os.Parcelable;
diff --git a/core/java/android/tv/TvView.java b/media/java/android/media/tv/TvView.java
similarity index 98%
rename from core/java/android/tv/TvView.java
rename to media/java/android/media/tv/TvView.java
index 2d31701..126d739 100644
--- a/core/java/android/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package android.tv;
+package android.media.tv;
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.media.tv.TvInputManager.Session;
+import android.media.tv.TvInputManager.Session.FinishedInputEventCallback;
+import android.media.tv.TvInputManager.SessionCallback;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.TextUtils;
-import android.tv.TvInputManager.Session;
-import android.tv.TvInputManager.Session.FinishedInputEventCallback;
-import android.tv.TvInputManager.SessionCallback;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.InputEvent;
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index d781336..19b54a6 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -433,16 +433,14 @@
             case MTP_TYPE_STR:
             {
                 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
+                const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
                 if (stringValue) {
-                    const char* str = env->GetStringUTFChars(stringValue, NULL);
-                    if (str == NULL) {
-                        return MTP_RESPONSE_GENERAL_ERROR;
-                    }
                     packet.putString(str);
                     env->ReleaseStringUTFChars(stringValue, str);
                 } else {
                     packet.putEmptyString();
                 }
+                env->DeleteLocalRef(stringValue);
                 break;
              }
             default:
@@ -515,7 +513,7 @@
             break;
          }
         default:
-            ALOGE("unsupported type in getObjectPropertyValue\n");
+            ALOGE("unsupported type in setObjectPropertyValue\n");
             return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
     }
 
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 36c1d5c..ec87c6e 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -88,7 +88,7 @@
     private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
         /**
          * Creates a new container and copies resource there.
-         * @param paackageURI the uri of resource to be copied. Can be either
+         * @param packageURI the uri of resource to be copied. Can be either
          * a content uri or a file uri
          * @param cid the id of the secure container that should
          * be used for creating a secure container into which the resource
@@ -101,13 +101,13 @@
          */
         public String copyResourceToContainer(final Uri packageURI, final String cid,
                 final String key, final String resFileName, final String publicResFileName,
-                boolean isExternal, boolean isForwardLocked) {
+                boolean isExternal, boolean isForwardLocked, String abiOverride) {
             if (packageURI == null || cid == null) {
                 return null;
             }
 
             return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
-                    isExternal, isForwardLocked);
+                    isExternal, isForwardLocked, abiOverride);
         }
 
         /**
@@ -153,13 +153,12 @@
         /**
          * Determine the recommended install location for package
          * specified by file uri location.
-         * @param fileUri the uri of resource to be copied. Should be a
-         * file uri
+         *
          * @return Returns PackageInfoLite object containing
          * the package info and recommended app location.
          */
         public PackageInfoLite getMinimalPackageInfo(final String packagePath, int flags,
-                long threshold) {
+                long threshold, String abiOverride) {
             PackageInfoLite ret = new PackageInfoLite();
 
             if (packagePath == null) {
@@ -191,7 +190,7 @@
             ret.verifiers = pkg.verifiers;
 
             ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation,
-                    packagePath, flags, threshold);
+                    packagePath, flags, threshold, abiOverride);
 
             return ret;
         }
@@ -208,11 +207,11 @@
         }
 
         @Override
-        public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked)
-                throws RemoteException {
+        public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked,
+                String abiOverride) throws RemoteException {
             final File apkFile = new File(packageUri.getPath());
             try {
-                return isUnderExternalThreshold(apkFile, isForwardLocked);
+                return isUnderExternalThreshold(apkFile, isForwardLocked, abiOverride);
             } catch (IOException e) {
                 return true;
             }
@@ -265,11 +264,11 @@
         }
 
         @Override
-        public long calculateInstalledSize(String packagePath, boolean isForwardLocked)
-                throws RemoteException {
+        public long calculateInstalledSize(String packagePath, boolean isForwardLocked,
+                String abiOverride) throws RemoteException {
             final File packageFile = new File(packagePath);
             try {
-                return calculateContainerSize(packageFile, isForwardLocked) * 1024 * 1024;
+                return calculateContainerSize(packageFile, isForwardLocked, abiOverride) * 1024 * 1024;
             } catch (IOException e) {
                 /*
                  * Okay, something failed, so let's just estimate it to be 2x
@@ -328,7 +327,8 @@
     }
 
     private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
-            String publicResFileName, boolean isExternal, boolean isForwardLocked) {
+            String publicResFileName, boolean isExternal, boolean isForwardLocked,
+            String abiOverride) {
 
         if (isExternal) {
             // Make sure the sdcard is mounted.
@@ -343,7 +343,22 @@
         String codePath = packageURI.getPath();
         File codeFile = new File(codePath);
         NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);
-        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+        String[] abiList = Build.SUPPORTED_ABIS;
+        if (abiOverride != null) {
+            abiList = new String[] { abiOverride };
+        } else {
+            try {
+                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
+                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+                    abiList = Build.SUPPORTED_32_BIT_ABIS;
+                }
+            } catch (IOException ioe) {
+                Slog.w(TAG, "Problem determining ABI for: " + codeFile.getPath());
+                return null;
+            }
+        }
+
+        final int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
 
         // Calculate size of container needed to hold base APK.
         final int sizeMb;
@@ -414,7 +429,7 @@
             int ret = PackageManager.INSTALL_SUCCEEDED;
             if (abi >= 0) {
                 ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
-                        sharedLibraryDir, Build.SUPPORTED_ABIS[abi]);
+                        sharedLibraryDir, abiList[abi]);
             } else if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
                 ret = abi;
             }
@@ -672,7 +687,7 @@
     private static final int PREFER_EXTERNAL = 2;
 
     private int recommendAppInstallLocation(int installLocation, String archiveFilePath, int flags,
-            long threshold) {
+            long threshold, String abiOverride) {
         int prefer;
         boolean checkBoth = false;
 
@@ -741,7 +756,7 @@
         boolean fitsOnSd = false;
         if (!emulated && (checkBoth || prefer == PREFER_EXTERNAL)) {
             try {
-                fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked);
+                fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked, abiOverride);
             } catch (IOException e) {
                 return PackageHelper.RECOMMEND_FAILED_INVALID_URI;
             }
@@ -812,13 +827,13 @@
      * @return true if file fits
      * @throws IOException when file does not exist
      */
-    private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked)
+    private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked, String abiOverride)
             throws IOException {
         if (Environment.isExternalStorageEmulated()) {
             return false;
         }
 
-        final int sizeMb = calculateContainerSize(apkFile, isForwardLocked);
+        final int sizeMb = calculateContainerSize(apkFile, isForwardLocked, abiOverride);
 
         final int availSdMb;
         if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
@@ -832,9 +847,11 @@
         return availSdMb > sizeMb;
     }
 
-    private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
+    private int calculateContainerSize(File apkFile, boolean forwardLocked,
+            String abiOverride) throws IOException {
         NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
-        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+        final int abi = NativeLibraryHelper.findSupportedAbi(handle,
+                (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);
 
         try {
             return calculateContainerSize(handle, apkFile, abi, forwardLocked);
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index aa118ed..ae04e32 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="2783841764617238354">"Asiakirjat"</string>
-    <string name="title_open" msgid="4353228937663917801">"Avoinna alkaen"</string>
+    <string name="title_open" msgid="4353228937663917801">"Avaa sijainnista"</string>
     <string name="title_save" msgid="2433679664882857999">"Tallenna kohteeseen"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"Luo kansio"</string>
     <string name="menu_grid" msgid="6878021334497835259">"Ruudukkonäkymä"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 070b130..b85b518 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="2783841764617238354">"Documents"</string>
+    <string name="app_label" msgid="2783841764617238354">"Docs"</string>
     <string name="title_open" msgid="4353228937663917801">"Ouvrir à partir de"</string>
     <string name="title_save" msgid="2433679664882857999">"Enregistrer sous"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"Créer un dossier"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index e8944ec..8c9030d 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -20,14 +20,14 @@
     <string name="title_open" msgid="4353228937663917801">"បើក​ពី"</string>
     <string name="title_save" msgid="2433679664882857999">"រក្សា​ទុក​ទៅ"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"បង្កើត​ថត"</string>
-    <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាព​ក្រឡា"</string>
+    <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាព​ក្រឡា​"</string>
     <string name="menu_list" msgid="7279285939892417279">"ទិដ្ឋភាព​បញ្ជី"</string>
     <string name="menu_sort" msgid="7677740407158414452">"តម្រៀប​តាម"</string>
     <string name="menu_search" msgid="3816712084502856974">"ស្វែងរក"</string>
     <string name="menu_settings" msgid="6008033148948428823">"ការ​កំណត់"</string>
     <string name="menu_open" msgid="432922957274920903">"បើក"</string>
     <string name="menu_save" msgid="2394743337684426338">"រក្សាទុក"</string>
-    <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក"</string>
+    <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក​"</string>
     <string name="menu_delete" msgid="8138799623850614177">"លុប"</string>
     <string name="menu_select" msgid="8711270657353563424">"ជ្រើស \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"បាន​ជ្រើស <xliff:g id="COUNT">%1$d</xliff:g>"</string>
@@ -48,7 +48,7 @@
     <string name="pref_advanced_devices" msgid="903257239609301276">"បង្ហាញ​ឧបករណ៍​កម្រិត​ខ្ពស់"</string>
     <string name="pref_file_size" msgid="2826879315743961459">"បង្ហាញ​ទំហំ​ឯកសារ"</string>
     <string name="pref_device_size" msgid="3542106883278997222">"បង្ហាញ​ទំហំ​ឧបករណ៍"</string>
-    <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ"</string>
+    <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ​"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"មិន​អាច​បើក​ឯកសារ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"មិន​អាច​លុប​ឯកសារ​មួយ​ចំនួន"</string>
     <string name="share_via" msgid="8966594246261344259">"ចែករំលែក​តាម"</string>
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 1be44f9..96ed2e7 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -16,8 +16,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) \
-                   $(call all-proto-files-under,src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files)
 
 LOCAL_MODULE := Keyguard
 
@@ -27,9 +26,6 @@
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index a2e54a7..18b59f1 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -83,7 +83,7 @@
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
-    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់"</string>
+    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
     <string name="keyboardview_keycode_done" msgid="1992571118466679775">"រួចរាល់"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ប្ដូរ​របៀប"</string>
@@ -120,7 +120,7 @@
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ព្យាយាម​លំនាំ​ច្រើន​ពេក"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"ដើម្បី​ដោះ​សោ ចូល​ក្នុង​គណនី Google ។"</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"ឈ្មោះ​អ្នក​ប្រើ (អ៊ី​ម៉ែ​ល​)"</string>
-    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់​"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"ចូល"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ភ្លេច​ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
deleted file mode 100644
index 20af2f1..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
+++ /dev/null
@@ -1,278 +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.keyguard.analytics;
-
-import com.google.protobuf.nano.CodedOutputByteBufferNano;
-import com.google.protobuf.nano.MessageNano;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.AsyncTask;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Tracks sessions, touch and sensor events in Keyguard.
- *
- * A session starts when the user is presented with the Keyguard and ends when the Keyguard is no
- * longer visible to the user.
- */
-public class KeyguardAnalytics implements SensorEventListener {
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "KeyguardAnalytics";
-    private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
-
-    private static final int[] SENSORS = new int[] {
-            Sensor.TYPE_ACCELEROMETER,
-            Sensor.TYPE_GYROSCOPE,
-            Sensor.TYPE_PROXIMITY,
-            Sensor.TYPE_LIGHT,
-            Sensor.TYPE_ROTATION_VECTOR,
-    };
-
-    private Session mCurrentSession = null;
-    // Err on the side of caution, so logging is not started after a crash even tough the screen
-    // is off.
-    private boolean mScreenOn = false;
-    private boolean mHidden = false;
-
-    private final SensorManager mSensorManager;
-    private final SessionTypeAdapter mSessionTypeAdapter;
-    private final File mAnalyticsFile;
-
-    public KeyguardAnalytics(Context context, SessionTypeAdapter sessionTypeAdapter,
-            File analyticsFile) {
-        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
-        mSessionTypeAdapter = sessionTypeAdapter;
-        mAnalyticsFile = analyticsFile;
-    }
-
-    public Callback getCallback() {
-        return mCallback;
-    }
-
-    public interface Callback {
-        public void onShow();
-        public void onHide();
-        public void onScreenOn();
-        public void onScreenOff();
-        public boolean onTouchEvent(MotionEvent ev, int width, int height);
-        public void onSetOccluded(boolean hidden);
-    }
-
-    public interface SessionTypeAdapter {
-        public int getSessionType();
-    }
-
-    private void sessionEntrypoint() {
-        if (mCurrentSession == null && mScreenOn && !mHidden) {
-            onSessionStart();
-        }
-    }
-
-    private void sessionExitpoint(int result) {
-        if (mCurrentSession != null) {
-            onSessionEnd(result);
-        }
-    }
-
-    private void onSessionStart() {
-        int type = mSessionTypeAdapter.getSessionType();
-        mCurrentSession = new Session(System.currentTimeMillis(), System.nanoTime(), type);
-        if (type == Session.TYPE_KEYGUARD_SECURE) {
-            mCurrentSession.setRedactTouchEvents();
-        }
-        for (int sensorType : SENSORS) {
-            Sensor s = mSensorManager.getDefaultSensor(sensorType);
-            if (s != null) {
-                mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
-            }
-        }
-        if (DEBUG) {
-            Log.d(TAG, "onSessionStart()");
-        }
-    }
-
-    private void onSessionEnd(int result) {
-        if (DEBUG) {
-            Log.d(TAG, String.format("onSessionEnd(success=%d)", result));
-        }
-        mSensorManager.unregisterListener(this);
-
-        Session session = mCurrentSession;
-        mCurrentSession = null;
-
-        session.end(System.currentTimeMillis(), result);
-        queueSession(session);
-    }
-
-    private void queueSession(final Session currentSession) {
-        if (DEBUG) {
-            Log.i(TAG, "Saving session.");
-        }
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                try {
-                    byte[] b = writeDelimitedProto(currentSession.toProto());
-                    OutputStream os = new FileOutputStream(mAnalyticsFile, true /* append */);
-                    if (DEBUG) {
-                        Log.d(TAG, String.format("Serialized size: %d kB.", b.length / 1024));
-                    }
-                    try {
-                        os.write(b);
-                        os.flush();
-                    } finally {
-                        try {
-                            os.close();
-                        } catch (IOException e) {
-                            Log.e(TAG, "Exception while closing file", e);
-                        }
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "Exception while writing file", e);
-                }
-                return null;
-            }
-
-            private byte[] writeDelimitedProto(MessageNano proto)
-                    throws IOException {
-                byte[] result = new byte[CodedOutputByteBufferNano.computeMessageSizeNoTag(proto)];
-                CodedOutputByteBufferNano ob = CodedOutputByteBufferNano.newInstance(result);
-                ob.writeMessageNoTag(proto);
-                ob.checkNoSpaceLeft();
-                return result;
-            }
-        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
-    }
-
-    @Override
-    public synchronized void onSensorChanged(SensorEvent event) {
-        if (false) {
-            Log.v(TAG, String.format(
-                    "onSensorChanged(name=%s, values[0]=%f)",
-                    event.sensor.getName(), event.values[0]));
-        }
-        if (mCurrentSession != null) {
-            mCurrentSession.addSensorEvent(event, System.nanoTime());
-            enforceTimeout();
-        }
-    }
-
-    private void enforceTimeout() {
-        if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
-                > TIMEOUT_MILLIS) {
-            onSessionEnd(Session.RESULT_UNKNOWN);
-            if (DEBUG) {
-                Log.i(TAG, "Analytics timed out.");
-            }
-        }
-    }
-
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-    }
-
-    private final Callback mCallback = new Callback() {
-        @Override
-        public void onShow() {
-            if (DEBUG) {
-                Log.d(TAG, "onShow()");
-            }
-            synchronized (KeyguardAnalytics.this) {
-                sessionEntrypoint();
-            }
-        }
-
-        @Override
-        public void onHide() {
-            if (DEBUG) {
-                Log.d(TAG, "onHide()");
-            }
-            synchronized (KeyguardAnalytics.this) {
-                sessionExitpoint(Session.RESULT_SUCCESS);
-            }
-        }
-
-        @Override
-        public void onScreenOn() {
-            if (DEBUG) {
-                Log.d(TAG, "onScreenOn()");
-            }
-            synchronized (KeyguardAnalytics.this) {
-                mScreenOn = true;
-                sessionEntrypoint();
-            }
-        }
-
-        @Override
-        public void onScreenOff() {
-            if (DEBUG) {
-                Log.d(TAG, "onScreenOff()");
-            }
-            synchronized (KeyguardAnalytics.this) {
-                mScreenOn = false;
-                sessionExitpoint(Session.RESULT_FAILURE);
-            }
-        }
-
-        @Override
-        public boolean onTouchEvent(MotionEvent ev, int width, int height) {
-            if (DEBUG) {
-                Log.v(TAG, "onTouchEvent(ev.action="
-                        + MotionEvent.actionToString(ev.getAction()) + ")");
-            }
-            synchronized (KeyguardAnalytics.this) {
-                if (mCurrentSession != null) {
-                    mCurrentSession.addMotionEvent(ev);
-                    mCurrentSession.setTouchArea(width, height);
-                    enforceTimeout();
-                }
-            }
-            return true;
-        }
-
-        @Override
-        public void onSetOccluded(boolean hidden) {
-            synchronized (KeyguardAnalytics.this) {
-                if (hidden != mHidden) {
-                    if (DEBUG) {
-                        Log.d(TAG, "onSetOccluded(" + hidden + ")");
-                    }
-                    mHidden = hidden;
-                    if (hidden) {
-                        // Could have gone to camera on purpose / by falsing or an app could have
-                        // launched on top of the lockscreen.
-                        sessionExitpoint(Session.RESULT_UNKNOWN);
-                    } else {
-                        sessionEntrypoint();
-                    }
-                }
-            }
-        }
-    };
-
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java b/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java
deleted file mode 100644
index e68f751..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java
+++ /dev/null
@@ -1,109 +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.keyguard.analytics;
-
-import android.graphics.RectF;
-import android.util.FloatMath;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.TouchEvent.BoundingBox;
-
-/**
- * Takes motion events and tracks the length and bounding box of each pointer gesture as well as
- * the bounding box of the whole gesture.
- */
-public class PointerTracker {
-    private SparseArray<Pointer> mPointerInfoMap = new SparseArray<Pointer>();
-    private RectF mTotalBoundingBox = new RectF();
-
-    public void addMotionEvent(MotionEvent ev) {
-        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
-            float x = ev.getX();
-            float y = ev.getY();
-            mTotalBoundingBox.set(x, y, x, y);
-        }
-        for (int i = 0; i < ev.getPointerCount(); i++) {
-            int id = ev.getPointerId(i);
-            Pointer pointer = getPointer(id);
-            float x = ev.getX(i);
-            float y = ev.getY(i);
-            boolean down = ev.getActionMasked() == MotionEvent.ACTION_DOWN
-                    || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
-                            && ev.getActionIndex() == i);
-            pointer.addPoint(x, y, down);
-            mTotalBoundingBox.union(x, y);
-        }
-    }
-
-    public float getPointerLength(int id) {
-        return getPointer(id).length;
-    }
-
-    public BoundingBox getBoundingBox() {
-        return boundingBoxFromRect(mTotalBoundingBox);
-    }
-
-    public BoundingBox getPointerBoundingBox(int id) {
-        return boundingBoxFromRect(getPointer(id).boundingBox);
-    }
-
-    private BoundingBox boundingBoxFromRect(RectF f) {
-        BoundingBox bb = new BoundingBox();
-        bb.setHeight(f.height());
-        bb.setWidth(f.width());
-        return bb;
-    }
-
-    private Pointer getPointer(int id) {
-        Pointer p = mPointerInfoMap.get(id);
-        if (p == null) {
-            p = new Pointer();
-            mPointerInfoMap.put(id, p);
-        }
-        return p;
-    }
-
-    private static class Pointer {
-        public float length;
-        public final RectF boundingBox = new RectF();
-
-        private float mLastX;
-        private float mLastY;
-
-        public void addPoint(float x, float y, boolean down) {
-            float deltaX;
-            float deltaY;
-            if (down) {
-                boundingBox.set(x, y, x, y);
-                length = 0f;
-                deltaX = 0;
-                deltaY = 0;
-            } else {
-                deltaX = x - mLastX;
-                deltaY = y - mLastY;
-            }
-            mLastX = x;
-            mLastY = y;
-            length += FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY);
-            boundingBox.union(x, y);
-        }
-    }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/Session.java b/packages/Keyguard/src/com/android/keyguard/analytics/Session.java
deleted file mode 100644
index 05f9165..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/Session.java
+++ /dev/null
@@ -1,220 +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.keyguard.analytics;
-
-import android.os.Build;
-import android.util.Slog;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-
-import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.SensorEvent;
-import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.TouchEvent;
-
-/**
- * Records data about one keyguard session.
- *
- * The recorded data contains start and end of the session, whether it unlocked the device
- * successfully, sensor data and touch data.
- *
- * If the keyguard is secure, the recorded touch data will correlate or contain the user pattern or
- * PIN. If this is not desired, the touch coordinates can be redacted before serialization.
- */
-public class Session {
-
-    private static final String TAG = "KeyguardAnalytics";
-    private static final boolean DEBUG = false;
-
-    /**
-     * The user has failed to unlock the device in this session.
-     */
-    public static final int RESULT_FAILURE = KeyguardAnalyticsProtos.Session.FAILURE;
-    /**
-     * The user has succeeded in unlocking the device in this session.
-     */
-    public static final int RESULT_SUCCESS = KeyguardAnalyticsProtos.Session.SUCCESS;
-
-    /**
-     * It is unknown how the session with the keyguard ended.
-     */
-    public static final int RESULT_UNKNOWN = KeyguardAnalyticsProtos.Session.UNKNOWN;
-
-    /**
-     * This session took place on an insecure keyguard.
-     */
-    public static final int TYPE_KEYGUARD_INSECURE
-            = KeyguardAnalyticsProtos.Session.KEYGUARD_INSECURE;
-
-    /**
-     * This session took place on an secure keyguard.
-     */
-    public static final int TYPE_KEYGUARD_SECURE
-            = KeyguardAnalyticsProtos.Session.KEYGUARD_SECURE;
-
-    /**
-     * This session took place during a fake wake up of the device.
-     */
-    public static final int TYPE_RANDOM_WAKEUP = KeyguardAnalyticsProtos.Session.RANDOM_WAKEUP;
-
-
-    private final PointerTracker mPointerTracker = new PointerTracker();
-
-    private final long mStartTimestampMillis;
-    private final long mStartSystemTimeNanos;
-    private final int mType;
-
-    private boolean mRedactTouchEvents;
-    private ArrayList<TouchEvent> mMotionEvents = new ArrayList<TouchEvent>(200);
-    private ArrayList<SensorEvent> mSensorEvents = new ArrayList<SensorEvent>(600);
-    private int mTouchAreaHeight;
-    private int mTouchAreaWidth;
-
-    private long mEndTimestampMillis;
-    private int mResult;
-    private boolean mEnded;
-
-    public Session(long startTimestampMillis, long startSystemTimeNanos, int type) {
-        mStartTimestampMillis = startTimestampMillis;
-        mStartSystemTimeNanos = startSystemTimeNanos;
-        mType = type;
-    }
-
-    public void end(long endTimestampMillis, int result) {
-        mEnded = true;
-        mEndTimestampMillis = endTimestampMillis;
-        mResult = result;
-    }
-
-    public void addMotionEvent(MotionEvent motionEvent) {
-        if (mEnded) {
-            return;
-        }
-        mPointerTracker.addMotionEvent(motionEvent);
-        mMotionEvents.add(protoFromMotionEvent(motionEvent));
-    }
-
-    public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
-        if (mEnded) {
-            return;
-        }
-        SensorEvent event = protoFromSensorEvent(eventOrig, systemTimeNanos);
-        mSensorEvents.add(event);
-        if (DEBUG) {
-            Slog.v(TAG, String.format("addSensorEvent(name=%s, values[0]=%f",
-                    event.getType(), event.values[0]));
-        }
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder("Session{");
-        sb.append("mType=").append(mType);
-        sb.append(", mStartTimestampMillis=").append(mStartTimestampMillis);
-        sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
-        sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
-        sb.append(", mResult=").append(mResult);
-        sb.append(", mRedactTouchEvents=").append(mRedactTouchEvents);
-        sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
-        sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
-        sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
-        sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public KeyguardAnalyticsProtos.Session toProto() {
-        KeyguardAnalyticsProtos.Session proto = new KeyguardAnalyticsProtos.Session();
-        proto.setStartTimestampMillis(mStartTimestampMillis);
-        proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis);
-        proto.setBuild(Build.FINGERPRINT);
-        proto.setResult(mResult);
-        proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
-        proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
-        proto.setTouchAreaWidth(mTouchAreaWidth);
-        proto.setTouchAreaHeight(mTouchAreaHeight);
-        proto.setType(mType);
-        if (mRedactTouchEvents) {
-            redactTouchEvents(proto.touchEvents);
-        }
-        return proto;
-    }
-
-    private void redactTouchEvents(TouchEvent[] touchEvents) {
-        for (int i = 0; i < touchEvents.length; i++) {
-            TouchEvent t = touchEvents[i];
-            for (int j = 0; j < t.pointers.length; j++) {
-                TouchEvent.Pointer p = t.pointers[j];
-                p.clearX();
-                p.clearY();
-            }
-            t.setRedacted(true);
-        }
-    }
-
-    private SensorEvent protoFromSensorEvent(android.hardware.SensorEvent ev, long sysTimeNanos) {
-        SensorEvent proto = new SensorEvent();
-        proto.setType(ev.sensor.getType());
-        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
-        proto.setTimestamp(ev.timestamp);
-        proto.values = ev.values.clone();
-        return proto;
-    }
-
-    private TouchEvent protoFromMotionEvent(MotionEvent ev) {
-        int count = ev.getPointerCount();
-        TouchEvent proto = new TouchEvent();
-        proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos);
-        proto.setAction(ev.getActionMasked());
-        proto.setActionIndex(ev.getActionIndex());
-        proto.pointers = new TouchEvent.Pointer[count];
-        for (int i = 0; i < count; i++) {
-            TouchEvent.Pointer p = new TouchEvent.Pointer();
-            p.setX(ev.getX(i));
-            p.setY(ev.getY(i));
-            p.setSize(ev.getSize(i));
-            p.setPressure(ev.getPressure(i));
-            p.setId(ev.getPointerId(i));
-            proto.pointers[i] = p;
-            if ((ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && ev.getActionIndex() == i)
-                    || ev.getActionMasked() == MotionEvent.ACTION_UP) {
-                p.boundingBox = mPointerTracker.getPointerBoundingBox(p.getId());
-                p.setLength(mPointerTracker.getPointerLength(p.getId()));
-            }
-        }
-        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
-            proto.boundingBox = mPointerTracker.getBoundingBox();
-        }
-        return proto;
-    }
-
-    /**
-     * Discards the x / y coordinates of the touch events on serialization. Retained are the
-     * size of the individual and overall bounding boxes and the length of each pointer's gesture.
-     */
-    public void setRedactTouchEvents() {
-        mRedactTouchEvents = true;
-    }
-
-    public void setTouchArea(int width, int height) {
-        mTouchAreaWidth = width;
-        mTouchAreaHeight = height;
-    }
-
-    public long getStartTimestampMillis() {
-        return mStartTimestampMillis;
-    }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto b/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto
deleted file mode 100644
index 68b1590..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto
+++ /dev/null
@@ -1,102 +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
- */
-
-syntax = "proto2";
-
-package keyguard;
-
-option java_package = "com.android.keyguard.analytics";
-option java_outer_classname = "KeyguardAnalyticsProtos";
-
-message Session {
-    message TouchEvent {
-        message BoundingBox {
-            optional float width = 1;
-            optional float height = 2;
-        }
-
-        enum Action {
-            // Keep in sync with MotionEvent.
-            DOWN = 0;
-            UP = 1;
-            MOVE = 2;
-            CANCEL = 3;
-            OUTSIDE = 4;
-            POINTER_DOWN = 5;
-            POINTER_UP = 6;
-        }
-
-        message Pointer {
-            optional float x = 1;
-            optional float y = 2;
-            optional float size = 3;
-            optional float pressure = 4;
-            optional int32 id = 5;
-            optional float length = 6;
-            // Bounding box of the pointer. Only set on UP or POINTER_UP event of this pointer.
-            optional BoundingBox boundingBox = 7;
-        }
-
-        optional uint64 timeOffsetNanos = 1;
-        optional Action action = 2;
-        optional int32 actionIndex = 3;
-        repeated Pointer pointers = 4;
-        /* If true, the the x / y coordinates of the touch events were redacted. Retained are the
-           size of the individual and overall bounding boxes and the length of each pointer's
-           gesture. */
-        optional bool redacted = 5;
-        // Bounding box of the whole gesture. Only set on UP event.
-        optional BoundingBox boundingBox = 6;
-    }
-
-    message SensorEvent {
-        enum Type {
-            ACCELEROMETER = 1;
-            GYROSCOPE = 4;
-            LIGHT = 5;
-            PROXIMITY = 8;
-            ROTATION_VECTOR = 11;
-        }
-
-        optional Type type = 1;
-        optional uint64 timeOffsetNanos = 2;
-        repeated float values = 3;
-        optional uint64 timestamp = 4;
-    }
-
-    enum Result {
-        FAILURE = 0;
-        SUCCESS = 1;
-        UNKNOWN = 2;
-    }
-
-    enum Type {
-        KEYGUARD_INSECURE = 0;
-        KEYGUARD_SECURE = 1;
-        RANDOM_WAKEUP = 2;
-    }
-
-    optional uint64 startTimestampMillis = 1;
-    optional uint64 durationMillis = 2;
-    optional string build = 3;
-    optional Result result = 4;
-    repeated TouchEvent touchEvents = 5;
-    repeated SensorEvent sensorEvents = 6;
-
-    optional int32 touchAreaWidth = 9;
-    optional int32 touchAreaHeight = 10;
-    optional Type type = 11;
-}
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c45254e..c642626 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Aan."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Af"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Gekoppel."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"USB-verbinding"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Warmkol"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Kennisgewings"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"ONLANGS"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Geen onlangse programme nie"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk word\ndalk gemonitor"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 5c4d98b..d864f9f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"በርቷል።"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"ጠፍቷል።"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"ተገናኝቷል።"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ብሉቱዝ <xliff:g id="STATE">%s</xliff:g>።"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"አካባቢ <xliff:g id="STATE">%s</xliff:g>።"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ማንቂያ ለ<xliff:g id="TIME">%s</xliff:g> ተዋቅሯል።"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ውሂብ ቦዝኗል"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G ውሂብ ቦዝኗል"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"የተንቀሳቃሽ ውሂብ ቦዝኗል"</string>
@@ -213,9 +212,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"ተጨማሪ ቅንብሮች"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"በማገናኘት ላይ"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"መገናኛ ነጥብ"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"የቅርብ ጊዜዎች"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ማሳወቂያዎች"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"ምንም የቅርብ ጊዜ መተግበሪያዎች የሉም"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"አውታረ መረብ\nክትትል ሊደረግበት ይችላል"</string>
@@ -234,10 +232,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"በጣም አስቸካይ ያልሆኑ ማሳወቂያዎች ከታች"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"ለመክፈት ዳግም መታ ያድርጉ"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"ይህን እስኪያጠፉት ድረስ"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"ለአንድ ደቂቃ"</item>
+    <item quantity="other" msgid="6924190729213550991">"ለ%d ደቂቃዎች"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"ለአንድ ሰዓት"</item>
+    <item quantity="other" msgid="5408537517529822157">"ለ%d ሰዓቶች"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d7c5651..3906bfa 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"تم التشغيل."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"تم الإيقاف."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"متصل."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1‎ X‎"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"النطاق"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطة اتصال"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"الإشعارات"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"الأخيرة"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"ليست هناك تطبيقات حديثة"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"قد تكون الشبكة\nخاضعة للرقابة"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2405804..6ef23ad 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Вкл."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Изкл."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Има връзка."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетъринг"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка за достъп"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известия"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"СКОРОШНИ"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Няма скорошни приложения"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежата може\nда се наблюдава"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 982e0c6..9e3495e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Activat."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivat."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connectat."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ancoratge a xarxa"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacions"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"No hi ha aplicacions recents."</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"És possible que la xarxa\nestigui controlada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 570e1bb..6050da4 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Zapnuto."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Vypnuto."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Připojeno."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Sdílení datového připojení"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Oznámení"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"POSLEDNÍ"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Žádné nedávné aplikace"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Síť může být\nmonitorována"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 127192a..830bebf 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Til."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Fra."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Forbundet."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Underretninger"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"SENESTE"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Der er ingen seneste apps"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netværket kan\nvære overvåget"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c9c7b8e..72c9d64 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"An"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Aus"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Verbunden"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Benachrichtigungen"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"Letzte"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Keine neuen Apps"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netzwerk wird\neventuell überwacht."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1d90dae..2d3f246 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Ενεργό."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Ανενεργό."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Έχει συνδεθεί."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Πρόσδεση"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Σημείο πρόσβασης Wi-Fi"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ειδοποιήσεις"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"ΠΡΟΣΦΑΤΑ"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Καμία πρόσφατη εφαρμογή"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Το δίκτυο μπορεί\nνα παρακολουθείται"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a9c6678..66233cc 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"On."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Off."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connected."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a9c6678..66233cc 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"On."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Off."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connected."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6ca4ebc..0810ee7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Activado"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivado"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,8 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECIENTES"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
+    <skip />
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Es posible que la red\nesté supervisada."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d0e9c0a..ad92c24 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Sí"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"No"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECIENTES"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"No hay aplicaciones recientes"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La red se\npuede supervisar"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index c692b28..71e2af6 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Sees."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Väljas."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ühendatud."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jagamine"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Leviala"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Märguanded"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"HILJUTISED"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Hiljutisi rakendusi pole"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Võrku võidakse\njälgida"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index ee2c48d..3ea2110 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"روشن."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"خاموش."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"متصل."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"اتصال به اینترنت با تلفن همراه"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطه اتصال"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"اعلان‌ها"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"موارد اخیر"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"هیچ برنامه جدیدی موجود نیست"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ممکن است شبکه\nتحت نظارت باشد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 44d35b3..eb68ea6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Käytössä."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Pois käytöstä."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Yhdistetty."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,8 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jaettu yhteys"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ilmoitukset"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"VIIMEISIMMÄT"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
+    <skip />
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Verkkoa saatetaan\nvalvoa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index d9790f6..4c1df8c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Activé"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Désactivé"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connecté"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1x"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"3G+"</string>
@@ -158,12 +160,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Localisation <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Fermer le panneau"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Plus longtemps"</string>
+    <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Moins longtemps"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G  désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Données mobiles désactivées"</string>
@@ -215,9 +214,9 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès sans fil"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"RÉCENTS"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
@@ -236,10 +235,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes affichées ci-dessous"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Touchez à nouveau pour ouvrir"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
+    <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
+    <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d95fe06..bd709a0 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Activé"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Désactivé"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connecté"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1x"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Localisation <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Fermer le panneau"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Plus longtemps"</string>
+    <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Moins longtemps"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Données mobiles désactivées"</string>
@@ -215,9 +214,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"RÉCENTS"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Aucune application récente"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
@@ -236,10 +234,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes ci-dessous"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Appuyer à nouveau pour ouvrir"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
+    <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
+    <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 60d7de1..d6b6d6a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"चालू."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"बंद."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"कनेक्ट है."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचनाएं"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"हाल ही का"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"कोई हाल ही का ऐप्स नहीं"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्‍लिकेशन जानकारी"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"नेटवर्क को\nमॉनीटर किया जा सकता है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 09dde42..79d7003 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Uključeno."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Isključeno."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Povezano."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Žarišna točka"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavijesti"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"NEDAVNO"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Nema nedavnih aplikacija"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mreža se\nmožda prati"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index dc85416..915f5eb 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Bekapcsolva."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Kikapcsolva."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Csatlakoztatva."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Megosztás"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Értesítések"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"LEGUTÓBBIAK"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Nincs újabb alkalmazás"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Lehet, hogy a\nhálózat felügyelt"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index b11a004..ca327d8 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Միացված է:"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Անջատված է:"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Միացված է:"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth-ը <xliff:g id="STATE">%s</xliff:g> է:"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Տեղադրությունը՝ <xliff:g id="STATE">%s</xliff:g>:"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Զարթուցիչը դրված է <xliff:g id="TIME">%s</xliff:g>-ին:"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G տվյալները անջատված են"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G տվյալները անջատված են"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Շարժական տվյալները անջատված են"</string>
@@ -213,9 +212,9 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Հավելյալ կարգավորումներ"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Միացում"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"ՎԵՐՋԻՆՆԵՐԸ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ցանցը կարող է\nվերահսկվել"</string>
@@ -234,10 +233,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Պակաս հրատապ ծանուցումները ստորև"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Կրկին հպեք՝ բացելու համար"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Քանի դեռ չեք անջատել"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Մեկ րոպե"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d րոպե"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Մեկ ժամ"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d ժամ"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f62209f..48c9a6d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Aktif."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Nonaktif."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Tersambung."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Menambatkan"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"TERBARU"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Tidak ada aplikasi terkini"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Jaringan bisa\ndiawasi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6cf13be..8653c8f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"ON"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"OFF"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connesso."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"MESSAGGI RECENTI"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Nessuna app recente"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La rete potrebbe\nessere monitorata"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4f07006..3279bc1 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"פועל."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"כבוי."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"מחובר."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"‎1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"שיתוף אינטרנט בין ניידים"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"נקודה לשיתוף אינטרנט"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"הודעות"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"אחרונים"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"אין אפליקציות אחרונות"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ייתכן שהרשת\nמנוטרת"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 84bbf8b..a1f7b5e 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"ON"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"OFF"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"接続済みです。"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"現在地: <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"アラームは<xliff:g id="TIME">%s</xliff:g>に設定されています。"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G~3Gデータが無効になりました"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4Gデータが無効になりました"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"モバイルデータが無効になりました"</string>
@@ -215,9 +214,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"詳細設定"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"テザリング"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"アクセスポイント"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"最近"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"最近使ったアプリはありません"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ネットワークが監視される\n場合があります"</string>
@@ -236,10 +234,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"緊急度の低い通知を下に表示"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"ユーザーがOFFにするまで"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"1分"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d分"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"1時間"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d時間"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index c31ea24..a1862da 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"ჩართული"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"გამორთულია."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"დაკავშირებულია."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"მდებარეობა <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"მაღვიძარა დაყენებულია: <xliff:g id="TIME">%s</xliff:g>"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ინტერნეტი გაითიშა."</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G მონაცემები გათიშულია"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"მობილური ინტერნეტი გაითიშა."</string>
@@ -213,9 +212,9 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"დამატებითი პარამეტრები"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"მოდემის რეჟიმი"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"წვდომის წერტილი"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"შეტყობინებები"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"ბოლო დროის"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"შესაძლოა ქსელზე\nმონიტორინგი ხორციელდებოდეს"</string>
@@ -234,10 +233,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"ქვემოთ მითითებულია ნაკლებად სასწრაფო შეტყობინებები"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"შეეხეთ ისევ გასახსნელად"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"სანამ ამას გამორთავდეთ"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"ერთი წუთით"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d წუთით"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"ერთი საათით"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d საათით"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index a9cf7d6..3f5b844 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -64,7 +64,7 @@
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"រូបថត​អេក្រង់​កំពុង​ត្រូវ​បាន​រក្សាទុក។"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។"</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។​"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ​ដើម្បី​មើល​រូបថត​អេក្រង់​របស់​អ្នក​។"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"មិន​អាច​រក្សាទុក​រូបថត​អេក្រង់​។ ឧបករណ៍​ផ្ទុក​អាច​កំពុង​ប្រើ​​។"</string>
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"បើក។"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"បិទ"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"បាន​តភ្ជាប់។"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -140,7 +142,7 @@
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាត​ការ​ជូន​ដំណឹង។"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"បាន​បើក GPS ។"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល​​ GPS ។"</string>
-    <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ"</string>
+    <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ​"</string>
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"កម្មវិធី​រោទ៍​ញ័រ។"</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"កម្មវិធី​រោទ៍​ស្ងាត់។"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
@@ -190,7 +192,7 @@
     <string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"ចាក់​សោ​​បញ្ឈរ"</string>
     <string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"ចាក់​សោ​​​ផ្ដេក"</string>
     <string name="quick_settings_ime_label" msgid="7073463064369468429">"វិធីសាស្ត្រ​បញ្ចូល"</string>
-    <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង"</string>
+    <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង​"</string>
     <string name="quick_settings_location_off_label" msgid="7464544086507331459">"ទីតាំង​បាន​បិទ"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"ឧបករណ៍​មេឌៀ"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
@@ -211,10 +213,11 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"ការ​ភ្ជាប់"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ហតស្ប៉ត"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ការ​ជូនដំណឹង"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"ថ្មីៗ"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
+    <skip />
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មាន​កម្មវិធី"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
-    <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ"</string>
+    <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ​"</string>
     <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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index bb2e5c1..4772e54 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"사용"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"사용 안함"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"연결됨"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"테더링"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"핫스팟"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"알림"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"최근"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"최근에 사용한 앱 없음"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"네트워크가\n모니터링될 수 있음"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 7220777..d5117a9 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"ເປີດ."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"ປິດ."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"ເຊື່ອມ​ຕໍ່ແລ້ວ."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"​ການ​ປ່ອນ​ສັນ​ຍານ"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"​ຮັອດ​ສະ​ປອດ"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ການແຈ້ງເຕືອນ"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"ບໍ່​ດົນ​ມາ​ນີ້"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"ບໍ່​ມີ​ແອັບຯ​ທີ່​ຫາ​ກໍ​ໃຊ້"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ເຄືອຄ່າຍອາດ\nຖືກຕິດຕາມ"</string>
@@ -230,13 +232,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"ການ​ແຈ້ງເຕືອນ​ທີ່​ສຳຄັນ​ໜ້ອຍ​ກວ່າ​ຢູ່​ດ້ານ​ລຸ່ມ"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"ແຕະ​ອີກ​ຄັ້ງ​ເພື່ອ​ເປີດ"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນ​ຂຶ້ນ​ເພື່ອ​ປົດ​ລັອກ"</string>
-    <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ"</string>
+    <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ​"</string>
   <plurals name="zen_mode_duration_minutes">
-    <item quantity="one" msgid="9040808414992812341">"​ສຳ​ລັບ​ນຶ່ງ​ນາ​ທີ"</item>
-    <item quantity="other" msgid="6924190729213550991">"ສຳ​ລັບ %d ນາ​ທີ"</item>
+    <item quantity="one" msgid="9040808414992812341">"ເປັນ​ເວລາ​ນຶ່ງ​ນາ​ທີ"</item>
+    <item quantity="other" msgid="6924190729213550991">"ເປັນ​ເວລາ %d ນາ​ທີ"</item>
   </plurals>
   <plurals name="zen_mode_duration_hours">
-    <item quantity="one" msgid="3480040795582254384">"​ສຳ​ລັບນຶ່ງ​ຊົ່ວ​ໂມງ"</item>
-    <item quantity="other" msgid="5408537517529822157">"ສຳ​ລັບ %d ຊົ່ວ​ໂມງ"</item>
+    <item quantity="one" msgid="3480040795582254384">"ເປັນ​ເວລາ​ນຶ່ງ​ຊົ່ວ​ໂມງ"</item>
+    <item quantity="other" msgid="5408537517529822157">"ເປັນ​ເວລາ %d ຊົ່ວ​ໂມງ"</item>
   </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d0ebd54..574e559 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Įjungta."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Išjungta."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Prijungta."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Susiejimas"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Viešosios interneto prieigos taškas"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pranešimai"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"PASTARIEJI"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Nėra naujausių programų"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tinklas gali\nbūti stebimas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 23ce4a9..398553d 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Ieslēgts"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Izslēgts"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Savienojums ir izveidots."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,8 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Piesaiste"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tīklājs"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Paziņojumi"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"JAUNĀKIE"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
+    <skip />
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tīkls var\ntikt uzraudzīts"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index c00b7ed..6a2e79e 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Идэвхижсэн."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Унтраах"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Холбогдсон."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Блютүүт <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Байршил <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Сэрүүлгийг <xliff:g id="TIME">%s</xliff:g>-д тохируулсан."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G дата идэвхгүй болов"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G дата идэвхгүй байна"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобайл дата идэвхгүй болов"</string>
@@ -213,9 +212,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Өөр тохиргоо"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Модем болгох"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Сүлжээний цэг"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"СҮҮЛИЙН"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Мэдэгдэл"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Сүүлд ашигласан апп байхгүй"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Сүлжээ хянагдаж\nбайж болзошгүй"</string>
@@ -234,10 +232,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Нээхийн тулд дахин товшино уу"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Таныг унтраах хүртэл"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Нэг цагийн турш"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d цагийн турш"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 263fc46..7ae9b55 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Dihidupkan."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Dimatikan."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Disambungkan."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Lokasi <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Penggera ditetapkan pada <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Tutup panel"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Lagi masa"</string>
+    <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Kurang masa"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data 2G-3G dilumpuhkan"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data 4G dilumpuhkan"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data mudah alih dilumpuhkan"</string>
@@ -213,9 +212,9 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Lagi tetapan"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Penambatan"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tempat liputan"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"TERBAHARU"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rangkaian mungkin\nboleh dipantau"</string>
@@ -234,10 +233,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang penting di bawah"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item>
+    <item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item>
+    <item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 75706a2..e842c0f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"På."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Av."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Tilkoblet."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tilknytning"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Wi-Fi-sone"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Varsler"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"NYLIGE"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Ingen nylige apper"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nettverket kan\nvære overvåket"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c4bef68..360b71d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Ingeschakeld."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Uitgeschakeld."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Verbonden."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTE"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Geen recente apps"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk kan\nworden gecontroleerd"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 825dfec..25098d8 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Wł."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Wył."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Połączono."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Powiązanie"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Punkt dostępu"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Powiadomienia"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"OSTATNIE"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Brak ostatnio uruchomionych aplikacji"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieć może być\nmonitorowana"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f9ac828..34adc46 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Ativado."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Desativado."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ligado."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Associação"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTES"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Nenhuma aplicação recente"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode ser\nmonitorizada"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 1c13e62..e3b1f846 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Ligado."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Desligado."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Localização <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Fechar painel"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Mais tempo"</string>
+    <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Menos tempo"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dados 2G e 3G desativados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dados 4G desativados"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Dados móveis desativados"</string>
@@ -215,9 +214,9 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Mais configurações"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTES"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do aplicativo"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode estar\nsob monitoração"</string>
@@ -236,10 +235,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Por 1 minuto"</item>
+    <item quantity="other" msgid="6924190729213550991">"Por %d minutos"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Por 1 hora"</item>
+    <item quantity="other" msgid="5408537517529822157">"Por %d horas"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 00bf8c0..e6a3872 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -210,6 +210,8 @@
     <skip />
     <!-- no translation found for accessibility_desc_connected (8366256693719499665) -->
     <skip />
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
     <skip />
     <!-- no translation found for accessibility_data_connection_1x (994133468120244018) -->
@@ -392,7 +394,7 @@
     <skip />
     <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
     <skip />
-    <!-- no translation found for recents_empty_message (2269156590813544104) -->
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
     <!-- no translation found for recents_app_info_button_label (2890317189376000030) -->
     <skip />
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7ffa77c..9bc9178 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Activat."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Dezactivat."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectat."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Locație: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmă setată pentru <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datele 2G-3G au fost dezactivate"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datele 4G au fost dezactivate"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Datele mobile au fost dezactivate"</string>
@@ -213,9 +212,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Mai multe setări"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"RECENTE"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificări"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Nicio aplicație recentă"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string>
@@ -234,10 +232,13 @@
     <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>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Timp de un minut"</item>
+    <item quantity="other" msgid="6924190729213550991">"Timp de %d (de) minute"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Timp de o oră"</item>
+    <item quantity="other" msgid="5408537517529822157">"Timp de %d (de) ore"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d726428..619ebc2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Вкл."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Выкл."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Подключено"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступа"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Уведомления"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"НЕДАВНИЕ СООБЩЕНИЯ"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Ничего не найдено."</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Действия в сети\nмогут отслеживаться"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8debc9a..df880cf 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Zapnuté."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Vypnuté."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Pripojené."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Poloha: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Budík nastavený na <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dátové prenosy 2G a 3G sú zakázané"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dátové prenosy 4G sú zakázané"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilné dátové prenosy sú zakázané"</string>
@@ -215,9 +214,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Ďalšie nastavenia"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Zdieľanie dátového pripojenia"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"NEDÁVNE"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Upozornenia"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Žiadne nedávne aplikácie"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieť môže byť\nmonitorovaná"</string>
@@ -236,10 +234,13 @@
     <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>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Zariadenie odomknete prejdením prstom nahor"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Na jednu minútu"</item>
+    <item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Na jednu hodinu"</item>
+    <item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6171c16..d1170bd 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Vklopljen."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Izklopljen."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Povezan."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internet prek mobilne naprave"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Dostopna točka"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obvestila"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"NEDAVNI"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Ni nedavnih aplikacij"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Omrežje je\nlahko spremljano"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 14782e6..cfb6a2c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Укључено."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Искључено."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Повезано је."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Повезивање"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хотспот"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Обавештења"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"НАЈНОВИЈЕ"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Нема недавних апликација"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежа се можда\nнадгледа"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a7fb15d..4e3d72f 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Aktiverad."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Inaktiverad."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ansluten."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,8 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internetdelning"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Trådlös surfzon"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"NYA"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
+    <skip />
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nätverket kan\nvara övervakat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index b8d8c58c..9bab46e 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -118,6 +118,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Imewashwa."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Imezimwa."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Imeunganishwa."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -154,12 +156,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Mahali <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Kengele imewekwa <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Funga paneli ya maelezo"</string>
+    <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Muda zaidi"</string>
+    <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Muda kidogo"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data ya 2G-3G imelemazwa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data ya 4G imelemazwa"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data ya kifaa cha mkononi imelemazwa"</string>
@@ -211,9 +210,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Mipangilio zaidi"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Kusambaza mtandao"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Mtandao-hewa"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"YA HIVI KARIBUNI"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Arifa"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Hakuna programu za karibuni"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Huenda mtandao\nunafuatiliwa"</string>
@@ -232,10 +230,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Arifa zisizo za dharura sana ziko hapo chini"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Gonga tena ili ufungue"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Hadi utakapozima hili"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Kwa dakika moja"</item>
+    <item quantity="other" msgid="6924190729213550991">"Kwa dakika %d"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Kwa saa moja"</item>
+    <item quantity="other" msgid="5408537517529822157">"Kwa saa %d"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index dc75e78..4820071 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"เปิดอยู่"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"ปิดอยู่"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"เชื่อมต่อแล้ว"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"บลูทูธ <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"สถานที่ <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ตั้งเวลาปลุกไว้ที่ <xliff:g id="TIME">%s</xliff:g>"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"ปิดใช้งานข้อมูล 2G-3G แล้ว"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"ปิดใช้งานข้อมูล 4G แล้ว"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"ปิดใช้งานข้อมูลมือถือแล้ว"</string>
@@ -213,9 +212,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"การตั้งค่าเพิ่มเติม"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"การปล่อยสัญญาณ"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ฮอตสปอต"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"ล่าสุด"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"การแจ้งเตือน"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"ไม่มีแอปล่าสุด"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"เครือข่ายอาจ\nถูกตรวจสอบ"</string>
@@ -234,10 +232,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"การแจ้งเตือนที่เร่งด่วนน้อยด้านล่าง"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"กวาดขึ้นเพื่อปลดล็อก"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"จนกว่าคุณจะปิดฟังก์ชันนี้"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"1 นาที"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d นาที"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"1 ชั่วโมง"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d ชั่วโมง"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0713ddd..6c6af51 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Naka-on."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Naka-off."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Nakakonekta."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"<xliff:g id="STATE">%s</xliff:g> ng Bluetooth."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Lokasyon <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set para sa <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Di pinapagana ang 2G-3G na data"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Hindi pinapagana ang 4G na data"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Hindi pinapagana ang data ng mobile"</string>
@@ -213,9 +212,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Marami pang setting"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Nagte-tether"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"MGA KAMAKAILAN"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</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_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Maaaring\nsinusubaybayan ang network"</string>
@@ -234,10 +232,13 @@
     <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>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Mag-swipe pataas upang i-unlock"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Hanggang sa i-off mo ito"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Sa loob ng isang minuto"</item>
+    <item quantity="other" msgid="6924190729213550991">"Sa loob ng %d (na) minuto"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Sa loob ng isang oras"</item>
+    <item quantity="other" msgid="5408537517529822157">"Sa loob ng %d (na) oras"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c0ba250..85ba8fe 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Açık."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Kapalı."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Bağlandı."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Konum: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm saati: <xliff:g id="TIME">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G verileri devre dışı bırakıldı"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G verileri devre dışı"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobil veriler devre dışı"</string>
@@ -213,9 +212,9 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Diğer ayarlar"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirimler"</string>
+    <!-- no translation found for recents_empty_message (7883614615463619450) -->
     <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"SON İLETİLER"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ağ izleniyor\nolabilir"</string>
@@ -234,10 +233,13 @@
     <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>
     <string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"Siz bunu kapatana kadar"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"Bir dakika süreyle"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d dakika süreyle"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"Bir saat süreyle"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d saat süreyle"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index e149d7b..7f66e72 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Увімкнено."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Вимкнено."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Під’єднано."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступу"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Сповіщення"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"ОСТАННІ"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Немає останніх додатків"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мережа може\nвідстежуватися"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index f99c341..3ddea96 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Bật."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Tắt."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Đã kết nối."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"GẦN ĐÂY"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Không có ứng dụng nào gần đây"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mạng có thể\nđược giám sát"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6940b2c..934ac8c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"开启。"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"关闭。"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"已连接。"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"蓝牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_location" msgid="4577282329866813100">"位置信息服务<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"闹钟已设置为:<xliff:g id="TIME">%s</xliff:g>。"</string>
-    <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
-    <skip />
-    <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
-    <skip />
+    <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>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G 数据网络已停用"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G 数据网络已停用"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"移动数据网络已停用"</string>
@@ -215,9 +214,8 @@
     <string name="quick_settings_more_settings" msgid="326112621462813682">"更多设置"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"网络共享"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"热点"</string>
-    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
-    <skip />
-    <string name="recents_empty_message" msgid="2269156590813544104">"最近"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"最近没有用过任何应用"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"网络可能会\n受到监控"</string>
@@ -236,10 +234,13 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"不太紧急的通知会显示在下方"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"再次点按即可打开"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
-    <!-- no translation found for zen_mode_forever (7420011936770086993) -->
-    <skip />
-    <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
-    <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
-    <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
-    <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+    <string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string>
+  <plurals name="zen_mode_duration_minutes">
+    <item quantity="one" msgid="9040808414992812341">"1分钟"</item>
+    <item quantity="other" msgid="6924190729213550991">"%d分钟"</item>
+  </plurals>
+  <plurals name="zen_mode_duration_hours">
+    <item quantity="one" msgid="3480040795582254384">"1小时"</item>
+    <item quantity="other" msgid="5408537517529822157">"%d小时"</item>
+  </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 04c00f5..40b56fe 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"開啟。"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"關閉。"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"已連線。"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -160,7 +162,7 @@
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"鬧鐘已設定為:<xliff:g id="TIME">%s</xliff:g>。"</string>
     <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>
+    <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"較少時間"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"已停用 2G-3G 數據"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"已停用 4G 數據"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"已停用流動數據"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"熱點"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"近期"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網絡可能會\n受到監控"</string>
@@ -232,7 +234,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"不太緊急的通知會在下方顯示"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
-    <string name="zen_mode_forever" msgid="7420011936770086993">"手動關閉這項設定前一律啟用"</string>
+    <string name="zen_mode_forever" msgid="7420011936770086993">"直至您關閉這項設定"</string>
   <plurals name="zen_mode_duration_minutes">
     <item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
     <item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 4ffb01b..c1a48c4 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"開啟。"</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"關閉。"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"已連線。"</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"無線基地台"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"近期"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網路可能\n受到監控"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4c44972..af49a7f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -120,6 +120,8 @@
     <string name="accessibility_desc_on" msgid="2385254693624345265">"Vula."</string>
     <string name="accessibility_desc_off" msgid="6475508157786853157">"Vala."</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Ixhunyiwe."</string>
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
     <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"I-HSPA"</string>
@@ -211,7 +213,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ukusebenzisa njengemodemu"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"I-Hotspot"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Izaziso"</string>
-    <string name="recents_empty_message" msgid="2269156590813544104">"OKWAKAMUVA"</string>
+    <string name="recents_empty_message" msgid="7883614615463619450">"Azikho izinhlelo zokusebenza zakamuva"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Kungenzeka inethiwekhi\niqashiwe"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bfbdcf3..60a5643 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -319,6 +319,9 @@
     <!-- Volume panel z depth -->
     <dimen name="volume_panel_z">3dp</dimen>
 
+    <!-- Distance between notifications and header when they are considered to be colliding. -->
+    <dimen name="header_notifications_collide_distance">24dp</dimen>
+
     <!-- Move distance for the hint animations on the lockscreen (unlock, phone, camera)-->
     <dimen name="hint_move_distance">75dp</dimen>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f7b4994..4837a53 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -59,8 +59,6 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.MultiUserAvatarCache;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.analytics.KeyguardAnalytics;
-import com.android.keyguard.analytics.Session;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
@@ -70,7 +68,6 @@
 import java.io.File;
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
 
 
 /**
@@ -117,7 +114,6 @@
 public class KeyguardViewMediator extends SystemUI {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     final static boolean DEBUG = false;
-    private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
     private final static boolean DBG_WAKE = false;
 
     private final static String TAG = "KeyguardViewMediator";
@@ -199,8 +195,6 @@
 
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
-    private KeyguardAnalytics mKeyguardAnalytics;
-
     // these are protected by synchronized (this)
 
     /**
@@ -469,22 +463,6 @@
                 mViewMediatorCallback, mLockPatternUtils);
         final ContentResolver cr = mContext.getContentResolver();
 
-        if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
-                Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
-            mKeyguardAnalytics = new KeyguardAnalytics(mContext, new SessionTypeAdapter() {
-
-                @Override
-                public int getSessionType() {
-                    return mLockPatternUtils.isSecure() && !mUpdateMonitor.getUserHasTrust(
-                            mLockPatternUtils.getCurrentUser())
-                            ? Session.TYPE_KEYGUARD_SECURE
-                            : Session.TYPE_KEYGUARD_INSECURE;
-                }
-            }, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
-        } else {
-            mKeyguardAnalytics = null;
-        }
-
         mScreenOn = mPM.isScreenOn();
 
         mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
@@ -585,9 +563,6 @@
             } else {
                 doKeyguardLocked(null);
             }
-            if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
-                mKeyguardAnalytics.getCallback().onScreenOff();
-            }
         }
         KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why);
     }
@@ -830,9 +805,6 @@
                 updateActivityLockScreenState();
                 adjustStatusBarLocked();
             }
-            if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
-                mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
-            }
         }
     }
 
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 994b329..97aa993 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.MediaStore;
@@ -32,6 +33,10 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 
 /**
@@ -43,6 +48,11 @@
 
     final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
 
+    private static final Intent SECURE_CAMERA_INTENT =
+            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
+                    .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+    private static final Intent INSECURE_CAMERA_INTENT =
+            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
     private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
 
     private ImageView mCameraImageView;
@@ -51,6 +61,7 @@
 
     private ActivityStarter mActivityStarter;
     private UnlockMethodCache mUnlockMethodCache;
+    private LockPatternUtils mLockPatternUtils;
 
     public KeyguardBottomAreaView(Context context) {
         super(context);
@@ -72,10 +83,11 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mLockPatternUtils = new LockPatternUtils(mContext);
         mCameraImageView = (ImageView) findViewById(R.id.camera_button);
         mPhoneImageView = (ImageView) findViewById(R.id.phone_button);
         mLockIcon = (ImageView) findViewById(R.id.lock_icon);
-        watchForDevicePolicyChanges();
+        watchForCameraPolicyChanges();
         watchForAccessibilityChanges();
         updateCameraVisibility();
         updatePhoneVisibility();
@@ -88,8 +100,19 @@
         mActivityStarter = activityStarter;
     }
 
+    private Intent getCameraIntent() {
+        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
+                mLockPatternUtils.getCurrentUser());
+        return mLockPatternUtils.isSecure() && !currentUserHasTrust
+                ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+    }
+
     private void updateCameraVisibility() {
-        boolean visible = !isCameraDisabledByDpm();
+        ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
+                PackageManager.MATCH_DEFAULT_ONLY,
+                mLockPatternUtils.getCurrentUser());
+        boolean visible = !isCameraDisabledByDpm() && resolved != null;
         mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
     }
 
@@ -122,19 +145,12 @@
         return false;
     }
 
-    private void watchForDevicePolicyChanges() {
+    private void watchForCameraPolicyChanges() {
         final IntentFilter filter = new IntentFilter();
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
-        getContext().registerReceiver(new BroadcastReceiver() {
-            public void onReceive(Context context, Intent intent) {
-                post(new Runnable() {
-                    @Override
-                    public void run() {
-                        updateCameraVisibility();
-                    }
-                });
-            }
-        }, filter);
+        getContext().registerReceiverAsUser(mDevicePolicyReceiver,
+                UserHandle.ALL, filter, null, null);
+        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
     }
 
     private void watchForAccessibilityChanges() {
@@ -171,9 +187,12 @@
     }
 
     public void launchCamera() {
-        mContext.startActivityAsUser(
-                new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE),
-                UserHandle.CURRENT);
+        Intent intent = getCameraIntent();
+        if (intent == SECURE_CAMERA_INTENT) {
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+        } else {
+            mActivityStarter.startActivity(intent);
+        }
     }
 
     public void launchPhone() {
@@ -186,6 +205,7 @@
         super.onVisibilityChanged(changedView, visibility);
         if (changedView == this && visibility == VISIBLE) {
             updateTrust();
+            updateCameraVisibility();
         }
     }
 
@@ -214,5 +234,25 @@
     @Override
     public void onMethodSecureChanged(boolean methodSecure) {
         updateTrust();
+        updateCameraVisibility();
     }
+
+    private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
+        public void onReceive(Context context, Intent intent) {
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    updateCameraVisibility();
+                }
+            });
+        }
+    };
+
+    private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
+            new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onUserSwitchComplete(int userId) {
+            updateCameraVisibility();
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index dfd5a88..ee6d369 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -91,8 +92,12 @@
     private ValueAnimator mQsExpansionAnimator;
     private FlingAnimationUtils mFlingAnimationUtils;
     private int mStatusBarMinHeight;
+    private boolean mHeaderHidden;
+    private int mNotificationsHeaderCollideDistance;
 
     private Interpolator mFastOutSlowInInterpolator;
+    private Interpolator mFastOutLinearInterpolator;
+    private Interpolator mLinearOutSlowInInterpolator;
     private ObjectAnimator mClockAnimator;
     private int mClockAnimationTarget = -1;
     private int mTopPaddingAdjustment;
@@ -143,6 +148,10 @@
         mNotificationStackScroller.setOverscrollTopChangedListener(this);
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
                 android.R.interpolator.fast_out_slow_in);
+        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
+                android.R.interpolator.linear_out_slow_in);
+        mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(),
+                android.R.interpolator.fast_out_linear_in);
         mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
         mSwipeTranslationViews.add(mNotificationStackScroller);
         mSwipeTranslationViews.add(mKeyguardStatusView);
@@ -159,6 +168,8 @@
         mStatusBarMinHeight = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
         mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height);
+        mNotificationsHeaderCollideDistance =
+                getResources().getDimensionPixelSize(R.dimen.header_notifications_collide_distance);
         mClockPositionAlgorithm.loadDimens(getResources());
     }
 
@@ -708,6 +719,43 @@
             positionClockAndNotifications();
         }
         mNotificationStackScroller.setStackHeight(expandedHeight);
+        updateKeyguardHeaderVisibility();
+    }
+
+    /**
+     * Hides the header when notifications are colliding with it.
+     */
+    private void updateKeyguardHeaderVisibility() {
+        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
+                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+            boolean hidden = mNotificationStackScroller.getNotificationsTopY()
+                    <= mHeader.getBottom() + mNotificationsHeaderCollideDistance;
+            if (hidden && !mHeaderHidden) {
+                mHeader.animate()
+                        .alpha(0f)
+                        .withLayer()
+                        .translationY(-mHeader.getHeight()/2)
+                        .setInterpolator(mFastOutLinearInterpolator)
+                        .setDuration(200);
+            } else if (!hidden && mHeaderHidden) {
+                mHeader.animate()
+                        .alpha(1f)
+                        .withLayer()
+                        .translationY(0)
+                        .setInterpolator(mLinearOutSlowInInterpolator)
+                        .setDuration(200);
+            }
+            mHeaderHidden = hidden;
+        } else {
+            mHeader.animate().cancel();
+            mHeader.setAlpha(1f);
+            mHeader.setTranslationY(0f);
+            if (mHeader.getLayerType() != LAYER_TYPE_NONE) {
+                mHeader.setLayerType(LAYER_TYPE_NONE, null);
+            }
+            mHeaderHidden = false;
+        }
+
     }
 
     @Override
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 1344703..7c87580 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -95,7 +95,6 @@
         mTiles.add(new LocationTile(this));
         mTiles.add(new CastTile(this));
         mTiles.add(new HotspotTile(this));
-        mTiles.add(new BugreportTile(this));
 
         mUserTracker = new CurrentUserTracker(mContext) {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 6892b85..5c98d51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1609,6 +1609,13 @@
     }
 
     /**
+     * @return the y position of the first notification
+     */
+    public float getNotificationsTopY() {
+        return mTopPadding + getTranslationY();
+    }
+
+    /**
      * A listener that is notified when some child locations might have changed.
      */
     public interface OnChildLocationsChangedListener {
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 762d3df..0c16b78 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -35,6 +35,7 @@
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -51,6 +52,7 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.TypedValue;
@@ -345,8 +347,8 @@
     }
 
     private Action getBugReportAction() {
-        return new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
-                R.string.global_action_bug_report) {
+        return new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
+                R.string.bugreport_title) {
 
             public void onPress() {
                 AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
@@ -383,6 +385,14 @@
             public boolean showBeforeProvisioning() {
                 return false;
             }
+
+            @Override
+            public String getStatus() {
+                return mContext.getString(
+                        com.android.internal.R.string.bugreport_status,
+                        Build.VERSION.RELEASE,
+                        Build.ID);
+            }
         };
     }
 
@@ -640,6 +650,10 @@
             return true;
         }
 
+        public String getStatus() {
+            return null;
+        }
+
         abstract public void onPress();
 
         public View create(
@@ -649,7 +663,13 @@
             ImageView icon = (ImageView) v.findViewById(R.id.icon);
             TextView messageView = (TextView) v.findViewById(R.id.message);
 
-            v.findViewById(R.id.status).setVisibility(View.GONE);
+            TextView statusView = (TextView) v.findViewById(R.id.status);
+            final String status = getStatus();
+            if (!TextUtils.isEmpty(status)) {
+                statusView.setText(status);
+            } else {
+                statusView.setVisibility(View.GONE);
+            }
             if (mIcon != null) {
                 icon.setImageDrawable(mIcon);
                 icon.setScaleType(ScaleType.CENTER_CROP);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 5dc9e58..2eee853 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3419,9 +3419,8 @@
 
     private Drawable loadImageURI(Uri uri) {
         try {
-            final Context context = getContext();
-            return Drawable.createFromStreamThemed(
-                    context.getContentResolver().openInputStream(uri), null, context.getTheme());
+            return Drawable.createFromStream(
+                    getContext().getContentResolver().openInputStream(uri), null);
         } catch (Exception e) {
             Log.w(TAG, "Unable to open content: " + uri);
         }
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 723ab24..0e57232 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -231,10 +231,18 @@
 
     public void addObj(BaseObj obj) {
         if (obj != null) {
-            // FIXME: this is fine for 32-bit but needs a path for 64-bit
-            addI32((int)obj.getID(null));
+            if (RenderScript.sPointerSize == 8) {
+                addI64(obj.getID(null));
+            }
+            else {
+                addI32((int)obj.getID(null));
+            }
         } else {
-            addI32(0);
+            if (RenderScript.sPointerSize == 8) {
+                addI64(0);
+            } else {
+                addI32(0);
+            }
         }
     }
 
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 2222d2c..8cac22d 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -82,6 +82,12 @@
     */
     public static final long CREATE_FLAG_LOW_POWER = 0x0004;
 
+    /*
+     * Detect the bitness of the VM to allow FieldPacker to do the right thing.
+     */
+    static native int rsnSystemGetPointerSize();
+    static int sPointerSize;
+
     static {
         sInitialized = false;
         if (!SystemProperties.getBoolean("config.disable_renderscript", false)) {
@@ -99,6 +105,7 @@
                 System.loadLibrary("rs_jni");
                 _nInit();
                 sInitialized = true;
+                sPointerSize = rsnSystemGetPointerSize();
             } catch (UnsatisfiedLinkError e) {
                 Log.e(LOG_TAG, "Error loading RS jni library: " + e);
                 throw new RSRuntimeException("Error loading RS jni library: " + e);
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index 9e76f52..3176e28 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -67,6 +67,26 @@
     }
 
     /**
+     * Only intended for use by the generated derived classes.
+     *
+     * @param rs
+     * @hide
+     */
+    protected ScriptC(RenderScript rs, String resName, byte[] bitcode32, byte[] bitcode64) {
+        super(0, rs);
+        long id = 0;
+        if (RenderScript.sPointerSize == 4) {
+            id = internalStringCreate(rs, resName, bitcode32);
+        } else {
+            id = internalStringCreate(rs, resName, bitcode64);
+        }
+        if (id == 0) {
+            throw new RSRuntimeException("Loading of ScriptC script failed.");
+        }
+        setID(id);
+    }
+
+    /**
      * Name of the file that holds the object cache.
      */
     private static final String CACHE_PATH = "com.android.renderscript.cache";
@@ -113,4 +133,17 @@
         //        Log.v(TAG, "Create script for resource = " + resName);
         return rs.nScriptCCreate(resName, mCachePath, pgm, pgmLength);
     }
+
+    private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) {
+        // Create the RS cache path if we haven't done so already.
+        if (mCachePath == null) {
+            File f = new File(rs.mCacheDir, CACHE_PATH);
+            mCachePath = f.getAbsolutePath();
+            f.mkdirs();
+        }
+        //        Log.v(TAG, "Create script for resource = " + resName);
+        return rs.nScriptCCreate(resName, mCachePath, bitcode, bitcode.length);
+    }
+
+
 }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 18a2e31..ae39b05 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1573,6 +1573,12 @@
     free(prims);
 }
 
+static jint
+nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
+    return (jint)sizeof(void*);
+}
+
+
 // ---------------------------------------------------------------------------
 
 
@@ -1708,6 +1714,7 @@
 {"rsnMeshGetVertices",               "(JJ[JI)V",                              (void*)nMeshGetVertices },
 {"rsnMeshGetIndices",                "(JJ[J[II)V",                            (void*)nMeshGetIndices },
 
+{"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
 };
 
 static int registerFuncs(JNIEnv *_env)
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0082b1e..14c15a7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -26,6 +26,7 @@
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupTransport;
 import android.app.backup.FullBackup;
 import android.app.backup.RestoreSet;
 import android.app.backup.IBackupManager;
@@ -82,7 +83,6 @@
 import android.util.SparseArray;
 import android.util.StringBuilderPrinter;
 
-import com.android.internal.backup.BackupConstants;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.backup.IObbBackupService;
 import com.android.server.AppWidgetBackupBridge;
@@ -2098,7 +2098,7 @@
             }
 
             mAgentBinder = null;
-            mStatus = BackupConstants.TRANSPORT_OK;
+            mStatus = BackupTransport.TRANSPORT_OK;
 
             // Sanity check: if the queue is empty we have no work to do.
             if (mOriginalQueue.isEmpty()) {
@@ -2121,14 +2121,14 @@
                 EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
 
                 // If we haven't stored package manager metadata yet, we must init the transport.
-                if (mStatus == BackupConstants.TRANSPORT_OK && pmState.length() <= 0) {
+                if (mStatus == BackupTransport.TRANSPORT_OK && pmState.length() <= 0) {
                     Slog.i(TAG, "Initializing (wiping) backup state and transport storage");
                     addBackupTrace("initializing transport " + transportName);
                     resetBackupState(mStateDir);  // Just to make sure.
                     mStatus = mTransport.initializeDevice();
 
                     addBackupTrace("transport.initializeDevice() == " + mStatus);
-                    if (mStatus == BackupConstants.TRANSPORT_OK) {
+                    if (mStatus == BackupTransport.TRANSPORT_OK) {
                         EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
                     } else {
                         EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
@@ -2141,7 +2141,7 @@
                 // directly and use a synthetic BackupRequest.  We always run this pass
                 // because it's cheap and this way we guarantee that we don't get out of
                 // step even if we're selecting among various transports at run time.
-                if (mStatus == BackupConstants.TRANSPORT_OK) {
+                if (mStatus == BackupTransport.TRANSPORT_OK) {
                     PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
                             mPackageManager, allAgentPackages());
                     mStatus = invokeAgentForBackup(PACKAGE_MANAGER_SENTINEL,
@@ -2149,7 +2149,7 @@
                     addBackupTrace("PMBA invoke: " + mStatus);
                 }
 
-                if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
+                if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
                     // The backend reports that our dataset has been wiped.  Note this in
                     // the event log; the no-success code below will reset the backup
                     // state as well.
@@ -2158,13 +2158,13 @@
             } catch (Exception e) {
                 Slog.e(TAG, "Error in backup thread", e);
                 addBackupTrace("Exception in backup thread: " + e);
-                mStatus = BackupConstants.TRANSPORT_ERROR;
+                mStatus = BackupTransport.TRANSPORT_ERROR;
             } finally {
                 // If we've succeeded so far, invokeAgentForBackup() will have run the PM
                 // metadata and its completion/timeout callback will continue the state
                 // machine chain.  If it failed that won't happen; we handle that now.
                 addBackupTrace("exiting prelim: " + mStatus);
-                if (mStatus != BackupConstants.TRANSPORT_OK) {
+                if (mStatus != BackupTransport.TRANSPORT_OK) {
                     // if things went wrong at this point, we need to
                     // restage everything and try again later.
                     resetBackupState(mStateDir);  // Just to make sure.
@@ -2176,7 +2176,7 @@
         // Transport has been initialized and the PM metadata submitted successfully
         // if that was warranted.  Now we process the single next thing in the queue.
         void invokeNextAgent() {
-            mStatus = BackupConstants.TRANSPORT_OK;
+            mStatus = BackupTransport.TRANSPORT_OK;
             addBackupTrace("invoke q=" + mQueue.size());
 
             // Sanity check that we have work to do.  If not, skip to the end where
@@ -2236,39 +2236,39 @@
                         // done here as long as we're successful so far.
                     } else {
                         // Timeout waiting for the agent
-                        mStatus = BackupConstants.AGENT_ERROR;
+                        mStatus = BackupTransport.AGENT_ERROR;
                     }
                 } catch (SecurityException ex) {
                     // Try for the next one.
                     Slog.d(TAG, "error in bind/backup", ex);
-                    mStatus = BackupConstants.AGENT_ERROR;
+                    mStatus = BackupTransport.AGENT_ERROR;
                             addBackupTrace("agent SE");
                 }
             } catch (NameNotFoundException e) {
                 Slog.d(TAG, "Package does not exist; skipping");
                 addBackupTrace("no such package");
-                mStatus = BackupConstants.AGENT_UNKNOWN;
+                mStatus = BackupTransport.AGENT_UNKNOWN;
             } finally {
                 mWakelock.setWorkSource(null);
 
                 // If there was an agent error, no timeout/completion handling will occur.
                 // That means we need to direct to the next state ourselves.
-                if (mStatus != BackupConstants.TRANSPORT_OK) {
+                if (mStatus != BackupTransport.TRANSPORT_OK) {
                     BackupState nextState = BackupState.RUNNING_QUEUE;
                     mAgentBinder = null;
 
                     // An agent-level failure means we reenqueue this one agent for
                     // a later retry, but otherwise proceed normally.
-                    if (mStatus == BackupConstants.AGENT_ERROR) {
+                    if (mStatus == BackupTransport.AGENT_ERROR) {
                         if (MORE_DEBUG) Slog.i(TAG, "Agent failure for " + request.packageName
                                 + " - restaging");
                         dataChangedImpl(request.packageName);
-                        mStatus = BackupConstants.TRANSPORT_OK;
+                        mStatus = BackupTransport.TRANSPORT_OK;
                         if (mQueue.isEmpty()) nextState = BackupState.FINAL;
-                    } else if (mStatus == BackupConstants.AGENT_UNKNOWN) {
+                    } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
                         // Failed lookup of the app, so we couldn't bring up an agent, but
                         // we're otherwise fine.  Just drop it and go on to the next as usual.
-                        mStatus = BackupConstants.TRANSPORT_OK;
+                        mStatus = BackupTransport.TRANSPORT_OK;
                     } else {
                         // Transport-level failure means we reenqueue everything
                         revertAndEndBackup();
@@ -2297,7 +2297,7 @@
             // If everything actually went through and this is the first time we've
             // done a backup, we can now record what the current backup dataset token
             // is.
-            if ((mCurrentToken == 0) && (mStatus == BackupConstants.TRANSPORT_OK)) {
+            if ((mCurrentToken == 0) && (mStatus == BackupTransport.TRANSPORT_OK)) {
                 addBackupTrace("success; recording token");
                 try {
                     mCurrentToken = mTransport.getCurrentRestoreSet();
@@ -2314,7 +2314,7 @@
             // state machine sequence and the wakelock is refcounted.
             synchronized (mQueueLock) {
                 mBackupRunning = false;
-                if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
+                if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
                     // Make sure we back up everything and perform the one-time init
                     clearMetadata();
                     if (DEBUG) Slog.d(TAG, "Server requires init; rerunning");
@@ -2395,7 +2395,7 @@
                 EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName,
                         e.toString());
                 agentErrorCleanup();
-                return BackupConstants.AGENT_ERROR;
+                return BackupTransport.AGENT_ERROR;
             }
 
             // At this point the agent is off and running.  The next thing to happen will
@@ -2403,7 +2403,7 @@
             // for transport, or a timeout.  Either way the next phase will happen in
             // response to the TimeoutHandler interface callbacks.
             addBackupTrace("invoke success");
-            return BackupConstants.TRANSPORT_OK;
+            return BackupTransport.TRANSPORT_OK;
         }
 
         public void failAgent(IBackupAgent agent, String message) {
@@ -2484,11 +2484,11 @@
             addBackupTrace("operation complete");
 
             ParcelFileDescriptor backupData = null;
-            mStatus = BackupConstants.TRANSPORT_OK;
+            mStatus = BackupTransport.TRANSPORT_OK;
             try {
                 int size = (int) mBackupDataName.length();
                 if (size > 0) {
-                    if (mStatus == BackupConstants.TRANSPORT_OK) {
+                    if (mStatus == BackupTransport.TRANSPORT_OK) {
                         backupData = ParcelFileDescriptor.open(mBackupDataName,
                                 ParcelFileDescriptor.MODE_READ_ONLY);
                         addBackupTrace("sending data to transport");
@@ -2501,7 +2501,7 @@
                     // renaming *all* the output state files (see below) until that happens.
 
                     addBackupTrace("data delivered: " + mStatus);
-                    if (mStatus == BackupConstants.TRANSPORT_OK) {
+                    if (mStatus == BackupTransport.TRANSPORT_OK) {
                         addBackupTrace("finishing op on transport");
                         mStatus = mTransport.finishBackup();
                         addBackupTrace("finished: " + mStatus);
@@ -2514,7 +2514,7 @@
                 // After successful transport, delete the now-stale data
                 // and juggle the files so that next time we supply the agent
                 // with the new state file it just created.
-                if (mStatus == BackupConstants.TRANSPORT_OK) {
+                if (mStatus == BackupTransport.TRANSPORT_OK) {
                     mBackupDataName.delete();
                     mNewStateName.renameTo(mSavedStateName);
                     EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
@@ -2525,7 +2525,7 @@
             } catch (Exception e) {
                 Slog.e(TAG, "Transport error backing up " + pkgName, e);
                 EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
-                mStatus = BackupConstants.TRANSPORT_ERROR;
+                mStatus = BackupTransport.TRANSPORT_ERROR;
             } finally {
                 try { if (backupData != null) backupData.close(); } catch (IOException e) {}
             }
@@ -2533,7 +2533,7 @@
             // If we encountered an error here it's a transport-level failure.  That
             // means we need to halt everything and reschedule everything for next time.
             final BackupState nextState;
-            if (mStatus != BackupConstants.TRANSPORT_OK) {
+            if (mStatus != BackupTransport.TRANSPORT_OK) {
                 revertAndEndBackup();
                 nextState = BackupState.FINAL;
             } else {
@@ -4847,7 +4847,7 @@
             mBackupHandler.removeMessages(MSG_RESTORE_TIMEOUT);
 
             // Assume error until we successfully init everything
-            mStatus = BackupConstants.TRANSPORT_ERROR;
+            mStatus = BackupTransport.TRANSPORT_ERROR;
 
             try {
                 // TODO: Log this before getAvailableRestoreSets, somehow
@@ -4902,7 +4902,7 @@
                 return;
             }
 
-            mStatus = BackupConstants.TRANSPORT_OK;
+            mStatus = BackupTransport.TRANSPORT_OK;
             executeNextState(RestoreState.DOWNLOAD_DATA);
         }
 
@@ -4917,7 +4917,7 @@
             try {
                 mStatus = mTransport.startRestore(mToken,
                         mRestorePackages.toArray(new PackageInfo[0]));
-                if (mStatus != BackupConstants.TRANSPORT_OK) {
+                if (mStatus != BackupTransport.TRANSPORT_OK) {
                     Slog.e(TAG, "Error starting restore operation");
                     EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                     executeNextState(RestoreState.FINAL);
@@ -4926,7 +4926,7 @@
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error communicating with transport for restore");
                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
-                mStatus = BackupConstants.TRANSPORT_ERROR;
+                mStatus = BackupTransport.TRANSPORT_ERROR;
                 executeNextState(RestoreState.FINAL);
                 return;
             }
@@ -4941,14 +4941,14 @@
                 if (packageName == null) {
                     Slog.e(TAG, "Error getting first restore package");
                     EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
-                    mStatus = BackupConstants.TRANSPORT_ERROR;
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
                     executeNextState(RestoreState.FINAL);
                     return;
                 } else if (packageName.equals("")) {
                     Slog.i(TAG, "No restore data available");
                     int millis = (int) (SystemClock.elapsedRealtime() - mStartRealtime);
                     EventLog.writeEvent(EventLogTags.RESTORE_SUCCESS, 0, millis);
-                    mStatus = BackupConstants.TRANSPORT_OK;
+                    mStatus = BackupTransport.TRANSPORT_OK;
                     executeNextState(RestoreState.FINAL);
                     return;
                 } else if (!packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
@@ -4979,7 +4979,7 @@
                     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 = BackupConstants.TRANSPORT_ERROR;
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
                     mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
                     executeNextState(RestoreState.FINAL);
                     return;
@@ -4987,7 +4987,7 @@
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error communicating with transport for restore");
                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
-                mStatus = BackupConstants.TRANSPORT_ERROR;
+                mStatus = BackupTransport.TRANSPORT_ERROR;
                 mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
                 executeNextState(RestoreState.FINAL);
                 return;
@@ -5118,7 +5118,7 @@
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Unable to fetch restore data from transport");
-                mStatus = BackupConstants.TRANSPORT_ERROR;
+                mStatus = BackupTransport.TRANSPORT_ERROR;
                 executeNextState(RestoreState.FINAL);
             }
         }
@@ -5206,7 +5206,7 @@
                     Slog.e(TAG, "SElinux restorecon failed for " + downloadFile);
                 }
 
-                if (mTransport.getRestoreData(stage) != BackupConstants.TRANSPORT_OK) {
+                if (mTransport.getRestoreData(stage) != BackupTransport.TRANSPORT_OK) {
                     // Transport-level failure, so we wind everything up and
                     // terminate the restore operation.
                     Slog.e(TAG, "Error getting restore data for " + packageName);
@@ -5450,12 +5450,12 @@
                     long startRealtime = SystemClock.elapsedRealtime();
                     int status = transport.initializeDevice();
 
-                    if (status == BackupConstants.TRANSPORT_OK) {
+                    if (status == BackupTransport.TRANSPORT_OK) {
                         status = transport.finishBackup();
                     }
 
                     // Okay, the wipe really happened.  Clean up our local bookkeeping.
-                    if (status == BackupConstants.TRANSPORT_OK) {
+                    if (status == BackupTransport.TRANSPORT_OK) {
                         Slog.i(TAG, "Device init successful");
                         int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
                         EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d7a19ad..b2b4217 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -38,7 +38,6 @@
 import static android.net.ConnectivityManager.TYPE_PROXY;
 import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
-import static android.net.ConnectivityServiceProtocol.NetworkFactoryProtocol;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 
@@ -80,6 +79,7 @@
 import android.net.NetworkConfig;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkFactory;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkState;
@@ -258,17 +258,6 @@
      */
     private NetworkStateTracker mNetTrackers[];
 
-    /**
-     * Holds references to all NetworkAgentInfos claiming to support the legacy
-     * NetworkType.  We used to have a static set of of NetworkStateTrackers
-     * for each network type.  This is the new model.
-     * Supports synchronous inspection of state.
-     * These are built out at startup such that an unsupported network
-     * doesn't get an ArrayList instance, making this a tristate:
-     * unsupported, supported but not active and active.
-     */
-    private ArrayList<NetworkAgentInfo> mNetworkAgentInfoForType[];
-
     /* Handles captive portal check on a network */
     private CaptivePortalTracker mCaptivePortalTracker;
 
@@ -516,6 +505,118 @@
 
     private static final int UID_UNUSED = -1;
 
+    /**
+     * Implements support for the legacy "one network per network type" model.
+     *
+     * We used to have a static array of NetworkStateTrackers, one for each
+     * network type, but that doesn't work any more now that we can have,
+     * for example, more that one wifi network. This class stores all the
+     * NetworkAgentInfo objects that support a given type, but the legacy
+     * API will only see the first one.
+     *
+     * It serves two main purposes:
+     *
+     * 1. Provide information about "the network for a given type" (since this
+     *    API only supports one).
+     * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
+     *    the first network for a given type changes, or if the default network
+     *    changes.
+     */
+    private class LegacyTypeTracker {
+        /**
+         * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
+         * Each list holds references to all NetworkAgentInfos that are used to
+         * satisfy requests for that network type.
+         *
+         * This array is built out at startup such that an unsupported network
+         * doesn't get an ArrayList instance, making this a tristate:
+         * unsupported, supported but not active and active.
+         *
+         * The actual lists are populated when we scan the network types that
+         * are supported on this device.
+         */
+        private ArrayList<NetworkAgentInfo> mTypeLists[];
+
+        public LegacyTypeTracker() {
+            mTypeLists = (ArrayList<NetworkAgentInfo>[])
+                    new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
+        }
+
+        public void addSupportedType(int type) {
+            if (mTypeLists[type] != null) {
+                throw new IllegalStateException(
+                        "legacy list for type " + type + "already initialized");
+            }
+            mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
+        }
+
+        private boolean isDefaultNetwork(NetworkAgentInfo nai) {
+            return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai;
+        }
+
+        public boolean isTypeSupported(int type) {
+            return isNetworkTypeValid(type) && mTypeLists[type] != null;
+        }
+
+        public NetworkAgentInfo getNetworkForType(int type) {
+            if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
+                return mTypeLists[type].get(0);
+            } else {
+                return null;
+            }
+        }
+
+        public void add(int type, NetworkAgentInfo nai) {
+            if (!isTypeSupported(type)) {
+                return;  // Invalid network type.
+            }
+            if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
+
+            ArrayList<NetworkAgentInfo> list = mTypeLists[type];
+            if (list.contains(nai)) {
+                loge("Attempting to register duplicate agent for type " + type + ": " + nai);
+                return;
+            }
+
+            if (list.isEmpty() || isDefaultNetwork(nai)) {
+                if (VDBG) log("Sending connected broadcast for type " + type +
+                              "isDefaultNetwork=" + isDefaultNetwork(nai));
+                sendLegacyNetworkBroadcast(nai, true, type);
+            }
+            list.add(nai);
+        }
+
+        public void remove(NetworkAgentInfo nai) {
+            if (VDBG) log("Removing agent " + nai);
+            for (int type = 0; type < mTypeLists.length; type++) {
+                ArrayList<NetworkAgentInfo> list = mTypeLists[type];
+                if (list == null || list.isEmpty()) {
+                    continue;
+                }
+
+                boolean wasFirstNetwork = false;
+                if (list.get(0).equals(nai)) {
+                    // This network was the first in the list. Send broadcast.
+                    wasFirstNetwork = true;
+                }
+                list.remove(nai);
+
+                if (wasFirstNetwork || isDefaultNetwork(nai)) {
+                    if (VDBG) log("Sending disconnected broadcast for type " + type +
+                                  "isDefaultNetwork=" + isDefaultNetwork(nai));
+                    sendLegacyNetworkBroadcast(nai, false, type);
+                }
+
+                if (!list.isEmpty() && wasFirstNetwork) {
+                    if (VDBG) log("Other network available for type " + type +
+                                  ", sending connected broadcast");
+                    sendLegacyNetworkBroadcast(list.get(0), false, type);
+                }
+            }
+        }
+    }
+    private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
+
     public ConnectivityService(Context context, INetworkManagementService netd,
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         // Currently, omitting a NetworkFactory will create one internally
@@ -531,7 +632,7 @@
         NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
         netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
-        mDefaultRequest = new NetworkRequest(netCap, true, nextNetworkRequestId());
+        mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
         NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
                 NetworkRequestInfo.REQUEST);
         mNetworkRequests.put(mDefaultRequest, nri);
@@ -587,9 +688,6 @@
         mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_networkTransitionTimeout);
 
-        mNetworkAgentInfoForType = (ArrayList<NetworkAgentInfo>[])
-                new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
-
         mNetTrackers = new NetworkStateTracker[
                 ConnectivityManager.MAX_NETWORK_TYPE+1];
         mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
@@ -644,7 +742,7 @@
                             "radio " + n.radio + " in network type " + n.type);
                     continue;
                 }
-                mNetworkAgentInfoForType[n.type] = new ArrayList<NetworkAgentInfo>();
+                mLegacyTypeTracker.addSupportedType(n.type);
 
                 mNetConfigs[n.type] = n;
                 mNetworksDefined++;
@@ -2843,7 +2941,8 @@
         }
     }
 
-    private int getRestoreDefaultNetworkDelay(int networkType) {
+    @Override
+    public int getRestoreDefaultNetworkDelay(int networkType) {
         String restoreDefaultNetworkDelayStr = SystemProperties.get(
                 NETWORK_RESTORE_DELAY_PROP_NAME);
         if(restoreDefaultNetworkDelayStr != null &&
@@ -2994,6 +3093,16 @@
                     updateNetworkInfo(nai, info);
                     break;
                 }
+                case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
+                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+                    if (nai == null) {
+                        loge("EVENT_NETWORK_SCORE_CHANGED from unknown NetworkAgent");
+                        break;
+                    }
+                    Integer score = (Integer) msg.obj;
+                    updateNetworkScore(nai, score);
+                    break;
+                }
                 case NetworkMonitor.EVENT_NETWORK_VALIDATED: {
                     NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
                     handleConnectionValidated(nai);
@@ -3098,7 +3207,7 @@
                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                     if (nri.isRequest == false) continue;
                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
-                    ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
+                    ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
                             (nai != null ? nai.currentScore : 0), 0, nri.request);
                 }
             } else {
@@ -3114,11 +3223,9 @@
             } else {
                 loge("Error connecting NetworkAgent");
                 NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
-                try {
-                    mNetworkAgentInfoForType[nai.networkInfo.getType()].remove(nai);
-                } catch (NullPointerException e) {}
                 if (nai != null) {
                     mNetworkForNetId.remove(nai.network.netId);
+                    mLegacyTypeTracker.remove(nai);
                 }
             }
         }
@@ -3137,14 +3244,19 @@
             } catch (Exception e) {
                 loge("Exception removing network: " + e);
             }
+            // TODO - if we move the logic to the network agent (have them disconnect
+            // because they lost all their requests or because their score isn't good)
+            // then they would disconnect organically, report their new state and then
+            // disconnect the channel.
+            if (nai.networkInfo.isConnected()) {
+                nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
+                        null, null);
+            }
             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
             mNetworkAgentInfos.remove(msg.replyTo);
             updateClat(null, nai.linkProperties, nai);
-            try {
-                mNetworkAgentInfoForType[nai.networkInfo.getType()].remove(nai);
-            } catch (NullPointerException e) {}
-
+            mLegacyTypeTracker.remove(nai);
             mNetworkForNetId.remove(nai.network.netId);
             // Since we've lost the network, go through all the requests that
             // it was satisfying and see if any other factory can satisfy them.
@@ -3154,7 +3266,7 @@
                 NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
                 if (VDBG) {
                     log(" checking request " + request + ", currentNetwork = " +
-                            currentNetwork != null ? currentNetwork.name() : "null");
+                            (currentNetwork != null ? currentNetwork.name() : "null"));
                 }
                 if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
                     mNetworkForRequestId.remove(request.requestId);
@@ -3203,7 +3315,11 @@
         }
         if (bestNetwork != null) {
             if (VDBG) log("using " + bestNetwork.name());
-            bestNetwork.networkRequests.put(nri.request.requestId, nri.request);
+            bestNetwork.addRequest(nri.request);
+            int legacyType = nri.request.legacyType;
+            if (legacyType != TYPE_NONE) {
+                mLegacyTypeTracker.add(legacyType, bestNetwork);
+            }
             notifyNetworkCallback(bestNetwork, nri);
             score = bestNetwork.currentScore;
         }
@@ -3211,7 +3327,8 @@
         if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
             if (DBG) log("sending new NetworkRequest to factories");
             for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
-                nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
+                nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
+                        0, nri.request);
             }
         }
     }
@@ -3233,7 +3350,8 @@
 
             if (nri.isRequest) {
                 for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
-                    nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
+                    nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
+                            nri.request);
                 }
 
                 if (affectedNetwork != null) {
@@ -5279,7 +5397,7 @@
 
     @Override
     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
-            Messenger messenger, int timeoutSec, IBinder binder) {
+            Messenger messenger, int timeoutSec, IBinder binder, int legacyType) {
         if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                 == false) {
             enforceConnectivityInternalPermission();
@@ -5291,7 +5409,7 @@
             throw new IllegalArgumentException("Bad timeout specified");
         }
         NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
-                networkCapabilities), false, nextNetworkRequestId());
+                networkCapabilities), legacyType, nextNetworkRequestId());
         if (DBG) log("requestNetwork for " + networkRequest);
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
                 NetworkRequestInfo.REQUEST);
@@ -5317,7 +5435,7 @@
         enforceAccessPermission();
 
         NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
-                networkCapabilities), false, nextNetworkRequestId());
+                networkCapabilities), TYPE_NONE, nextNetworkRequestId());
         if (DBG) log("listenForNetwork for " + networkRequest);
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
                 NetworkRequestInfo.LISTEN);
@@ -5392,18 +5510,13 @@
         NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), nextNetId(),
             new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
             new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler);
-
+        if (VDBG) log("registerNetworkAgent " + nai);
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
     }
 
     private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
         if (VDBG) log("Got NetworkAgent Messenger");
         mNetworkAgentInfos.put(na.messenger, na);
-        try {
-            mNetworkAgentInfoForType[na.networkInfo.getType()].add(na);
-        } catch (NullPointerException e) {
-            loge("registered NetworkAgent for unsupported type: " + na);
-        }
         mNetworkForNetId.put(na.network.netId, na);
         na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
         NetworkInfo networkInfo = na.networkInfo;
@@ -5439,7 +5552,7 @@
                 mClat.stopClat();
             }
             // If the link requires clat to be running, then start the daemon now.
-            if (newLp != null && na.networkInfo.isConnected()) {
+            if (na.networkInfo.isConnected()) {
                 mClat.startClat(na);
             } else {
                 mClat.stopClat();
@@ -5555,7 +5668,8 @@
     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
         if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
-            nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
+            nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
+                    networkRequest);
         }
     }
 
@@ -5658,7 +5772,11 @@
                         if (VDBG) log("   accepting network in place of null");
                     }
                     mNetworkForRequestId.put(nri.request.requestId, newNetwork);
-                    newNetwork.networkRequests.put(nri.request.requestId, nri.request);
+                    newNetwork.addRequest(nri.request);
+                    int legacyType = nri.request.legacyType;
+                    if (legacyType != TYPE_NONE) {
+                        mLegacyTypeTracker.add(legacyType, newNetwork);
+                    }
                     keep = true;
                     // TODO - this could get expensive if we have alot of requests for this
                     // network.  Think about if there is a way to reduce this.  Push
@@ -5672,6 +5790,7 @@
                         } else {
                             setDefaultDnsSystemProperties(new ArrayList<InetAddress>());
                         }
+                        mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
                     }
                 }
             }
@@ -5792,6 +5911,11 @@
         }
     }
 
+    private void updateNetworkScore(NetworkAgentInfo nai, Integer scoreInteger) {
+        int score = scoreInteger.intValue();
+        // TODO
+    }
+
     // notify only this one new request of the current state
     protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) {
         int notifyType = ConnectivityManager.CALLBACK_AVAILABLE;
@@ -5801,93 +5925,88 @@
 //        } else if (nai.networkMonitor.isEvaluating()) {
 //            notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType);
 //        }
-        if (nri.request.needsBroadcasts) {
-        // TODO
-//            sendNetworkBroadcast(nai, notifyType);
-        }
         callCallbackForRequest(nri, nai, notifyType);
     }
 
-    protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
-        if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name());
-        boolean needsBroadcasts = false;
-        for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
-            NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
-            NetworkRequestInfo nri = mNetworkRequests.get(nr);
-            if (VDBG) log(" sending notification for " + nr);
-            if (nr.needsBroadcasts) needsBroadcasts = true;
-            callCallbackForRequest(nri, networkAgent, notifyType);
-        }
-        if (needsBroadcasts) {
-            if (notifyType == ConnectivityManager.CALLBACK_AVAILABLE) {
-                sendConnectedBroadcastDelayed(networkAgent.networkInfo,
-                        getConnectivityChangeDelay());
-            } else if (notifyType == ConnectivityManager.CALLBACK_LOST) {
-                NetworkInfo info = new NetworkInfo(networkAgent.networkInfo);
-                Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
-                intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
-                intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
-                if (info.isFailover()) {
-                    intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
-                    networkAgent.networkInfo.setFailover(false);
-                }
-                if (info.getReason() != null) {
-                    intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
-                }
-                if (info.getExtraInfo() != null) {
-                    intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
-                }
-                NetworkAgentInfo newDefaultAgent = null;
-                if (networkAgent.networkRequests.get(mDefaultRequest.requestId) != null) {
-                    newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId);
-                    if (newDefaultAgent != null) {
-                        intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
-                                newDefaultAgent.networkInfo);
-                    } else {
-                        intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
-                    }
-                }
-                intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
-                        mDefaultInetConditionPublished);
-                final Intent immediateIntent = new Intent(intent);
-                immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
-                sendStickyBroadcast(immediateIntent);
-                sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
+    private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
+        if (connected) {
+            NetworkInfo info = new NetworkInfo(nai.networkInfo);
+            info.setType(type);
+            sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
+        } else {
+            NetworkInfo info = new NetworkInfo(nai.networkInfo);
+            info.setType(type);
+            Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
+            if (info.isFailover()) {
+                intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
+                nai.networkInfo.setFailover(false);
+            }
+            if (info.getReason() != null) {
+                intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
+            }
+            if (info.getExtraInfo() != null) {
+                intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
+            }
+            NetworkAgentInfo newDefaultAgent = null;
+            if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
+                newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId);
                 if (newDefaultAgent != null) {
-                    sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo,
-                            getConnectivityChangeDelay());
+                    intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
+                            newDefaultAgent.networkInfo);
+                } else {
+                    intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
                 }
             }
+            intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
+                    mDefaultInetConditionPublished);
+            final Intent immediateIntent = new Intent(intent);
+            immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
+            sendStickyBroadcast(immediateIntent);
+            sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
+            if (newDefaultAgent != null) {
+                sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo,
+                getConnectivityChangeDelay());
+            }
         }
     }
 
-    private LinkProperties getLinkPropertiesForTypeInternal(int networkType) {
-        ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType];
-        if (list == null) return null;
-        try {
-            return new LinkProperties(list.get(0).linkProperties);
-        } catch (IndexOutOfBoundsException e) {
-            return new LinkProperties();
+    protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
+        if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name());
+        for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
+            NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
+            NetworkRequestInfo nri = mNetworkRequests.get(nr);
+            if (VDBG) log(" sending notification for " + nr);
+            callCallbackForRequest(nri, networkAgent, notifyType);
         }
     }
 
+    private LinkProperties getLinkPropertiesForTypeInternal(int networkType) {
+        NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+        return (nai != null) ?
+                new LinkProperties(nai.linkProperties) :
+                new LinkProperties();
+    }
+
     private NetworkInfo getNetworkInfoForType(int networkType) {
-        ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType];
-        if (list == null) return null;
-        try {
-            return new NetworkInfo(list.get(0).networkInfo);
-        } catch (IndexOutOfBoundsException e) {
-            return new NetworkInfo(networkType, 0, "Unknown", "");
+        if (!mLegacyTypeTracker.isTypeSupported(networkType))
+            return null;
+
+        NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+        if (nai != null) {
+            NetworkInfo result = new NetworkInfo(nai.networkInfo);
+            result.setType(networkType);
+            return result;
+        } else {
+           return new NetworkInfo(networkType, 0, "Unknown", "");
         }
     }
 
     private NetworkCapabilities getNetworkCapabilitiesForType(int networkType) {
-        ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType];
-        if (list == null) return null;
-        try {
-            return new NetworkCapabilities(list.get(0).networkCapabilities);
-        } catch (IndexOutOfBoundsException e) {
-            return new NetworkCapabilities();
-        }
+        NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+        return (nai != null) ?
+                new NetworkCapabilities(nai.networkCapabilities) :
+                new NetworkCapabilities();
     }
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 11fc941..98fa522 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -427,8 +427,9 @@
         }
 
         // bind to fused provider if supported
-        if (FlpHardwareProvider.getInstance(mContext).isSupported()) {
-          FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
+        if (FlpHardwareProvider.isSupported()) {
+          FlpHardwareProvider flpHardwareProvider =
+              FlpHardwareProvider.getInstance(mContext);
           FusedProxy fusedProxy = FusedProxy.createAndBind(
                   mContext,
                   mLocationHandler,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 61ba6e0..aede797 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2978,6 +2978,10 @@
                 }
             }
             buf.append("}");
+            if (requiredAbi != null) {
+                buf.append(" abi=");
+                buf.append(requiredAbi);
+            }
             Slog.i(TAG, buf.toString());
             app.setPid(startResult.pid);
             app.usingWrapper = startResult.usingWrapper;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 16ad153..ba12374 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2537,7 +2537,9 @@
                     + " who=" + r.resultWho + " req=" + r.requestCode
                     + " res=" + resultCode + " data=" + resultData);
             if (resultTo.userId != r.userId) {
-                resultData.prepareToLeaveUser(r.userId);
+                if (resultData != null) {
+                    resultData.prepareToLeaveUser(r.userId);
+                }
             }
             if (r.info.applicationInfo.uid > 0) {
                 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 249422b..b492edd 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -623,10 +623,14 @@
         pw.println("  --charged: only output data since last charged.");
         pw.println("  --reset: reset the stats, clearing all current data.");
         pw.println("  --write: force write current collected stats to disk.");
-        pw.println("  --enable: enable an option: full-wake-history, no-auto-reset.");
-        pw.println("  --disable: disable an option: full-wake-history, no-auto-reset.");
-        pw.println("  -h: print this help text.");
         pw.println("  <package.name>: optional name of package to filter output by.");
+        pw.println("  -h: print this help text.");
+        pw.println("Battery stats (batterystats) commands:");
+        pw.println("  enable|disable <option>");
+        pw.println("    Enable or disable a running option.  Option state is not saved across boots.");
+        pw.println("    Options are:");
+        pw.println("      full-wake-history: include wake_lock_in battery history, full wake details.");
+        pw.println("      no-auto-reset: don't automatically reset stats when unplugged");
     }
 
     private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
@@ -702,14 +706,14 @@
                         pw.println("Battery stats written.");
                         noOutput = true;
                     }
-                } else if ("--enable".equals(arg)) {
+                } else if ("--enable".equals(arg) || "enable".equals(arg)) {
                     i = doEnableOrDisable(pw, i, args, true);
                     if (i < 0) {
                         return;
                     }
                     pw.println("Enabled: " + args[i]);
                     return;
-                } else if ("--disable".equals(arg)) {
+                } else if ("--disable".equals(arg) || "disable".equals(arg)) {
                     i = doEnableOrDisable(pw, i, args, false);
                     if (i < 0) {
                         return;
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 8102591..b03c247 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -45,7 +45,6 @@
     public int currentScore;
     public final NetworkMonitor networkMonitor;
 
-
     // The list of NetworkRequests being satisfied by this Network.
     public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
     public final ArrayList<NetworkRequest> networkLingered = new ArrayList<NetworkRequest>();
@@ -66,6 +65,10 @@
         networkMonitor = new NetworkMonitor(context, handler, this);
     }
 
+    public void addRequest(NetworkRequest networkRequest) {
+        networkRequests.put(networkRequest.requestId, networkRequest);
+    }
+
     public String toString() {
         return "NetworkAgentInfo{ ni{" + networkInfo + "}  network{" +
                 network + "}  lp{" +
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index d0b716d..5141d16a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -505,7 +505,7 @@
             // Reply <Feature Abort> to initiator (source) for all requests.
             HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand(
                     sourceAddress, message.getSource(), message.getOpcode(),
-                    HdmiCecMessageBuilder.ABORT_REFUSED);
+                    HdmiConstants.ABORT_REFUSED);
             sendCommand(cecMessage, null);
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 9a76734..6c2be34 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -26,15 +26,6 @@
  * A helper class to build {@link HdmiCecMessage} from various cec commands.
  */
 public class HdmiCecMessageBuilder {
-    // TODO: move these values to HdmiCec.java once make it internal constant class.
-    // CEC's ABORT reason values.
-    static final int ABORT_UNRECOGNIZED_MODE = 0;
-    static final int ABORT_NOT_IN_CORRECT_MODE = 1;
-    static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
-    static final int ABORT_INVALID_OPERAND = 3;
-    static final int ABORT_REFUSED = 4;
-    static final int ABORT_UNABLE_TO_DETERMINE = 5;
-
     private static final int OSD_NAME_MAX_LENGTH = 13;
 
     private HdmiCecMessageBuilder() {}
@@ -290,6 +281,64 @@
     }
 
     /**
+     * Build &lt;System Audio Mode Request&gt; command.
+     *
+     * @param src source address of command
+     * @param avr destination address of command, it should be AVR
+     * @param avrPhysicalAddress physical address of AVR
+     * @param enableSystemAudio whether to enable System Audio Mode or not
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildSystemAudioModeRequest(int src, int avr, int avrPhysicalAddress,
+            boolean enableSystemAudio) {
+        if (enableSystemAudio) {
+            return buildCommand(src, avr, HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
+                    physicalAddressToParam(avrPhysicalAddress));
+        } else {
+            return buildCommand(src, avr, HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST);
+        }
+    }
+
+    /**
+     * Build &lt;Give Audio Status&gt; command.
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildGiveAudioStatus(int src, int dest) {
+        return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_AUDIO_STATUS);
+    }
+
+    /**
+     * Build &lt;User Control Pressed&gt; command.
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @param uiCommand keycode that user pressed
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildUserControlPressed(int src, int dest, int uiCommand) {
+        byte[] params = new byte[] {
+                (byte) uiCommand
+        };
+        return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_PRESSED, params);
+    }
+
+    /**
+     * Build &lt;User Control Released&gt; command.
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildUserControlReleased(int src, int dest) {
+        return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_RELEASED);
+    }
+
+    /***** Please ADD new buildXXX() methods above. ******/
+
+    /**
      * Build a {@link HdmiCecMessage} without extra parameter.
      *
      * @param src source address of command
diff --git a/services/core/java/com/android/server/hdmi/HdmiConstants.java b/services/core/java/com/android/server/hdmi/HdmiConstants.java
new file mode 100644
index 0000000..a83d1ed
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiConstants.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hdmi;
+
+/**
+ * Defines constants related to HDMI-CEC protocol internal implementation.
+ * If a constant will be used in the public api, it should be located in
+ * {@link android.hardware.hdmi.HdmiCec}.
+ */
+final class HdmiConstants {
+
+    // Constants related to operands of HDMI CEC commands.
+    // Refer to CEC Table 29 in HDMI Spec v1.4b.
+    // [Abort Reason]
+    static final int ABORT_UNRECOGNIZED_MODE = 0;
+    static final int ABORT_NOT_IN_CORRECT_MODE = 1;
+    static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
+    static final int ABORT_INVALID_OPERAND = 3;
+    static final int ABORT_REFUSED = 4;
+    static final int ABORT_UNABLE_TO_DETERMINE = 5;
+
+    // [Audio Status]
+    static final int SYSTEM_AUDIO_STATUS_OFF = 0;
+    static final int SYSTEM_AUDIO_STATUS_ON = 1;
+
+    // Constants related to UI Command Codes.
+    // Refer to CEC Table 30 in HDMI Spec v1.4b.
+    static final int UI_COMMAND_MUTE = 0x43;
+    static final int UI_COMMAND_MUTE_FUNCTION = 0x65;
+    static final int UI_COMMAND_RESTORE_VOLUME_FUNCTION = 0x66;
+
+    private HdmiConstants() { /* cannot be instantiated */ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index d775733..0f3fc21 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -118,8 +118,11 @@
     // TODO: it may need to hold lock if it's accessed from others.
     private boolean mArcStatusEnabled = false;
 
+    // Whether SystemAudioMode is "On" or not.
+    private boolean mSystemAudioMode;
+
     // Handler running on service thread. It's used to run a task in service thread.
-    private Handler mHandler = new Handler();
+    private final Handler mHandler = new Handler();
 
     public HdmiControlService(Context context) {
         super(context);
@@ -158,6 +161,9 @@
         }
 
         publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
+
+        // TODO: Read the preference for SystemAudioMode and initialize mSystemAudioMode and
+        // start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
     }
 
     /**
@@ -211,35 +217,43 @@
      * @param action {@link FeatureAction} to remove
      */
     void removeAction(final FeatureAction action) {
-        runOnServiceThread(new Runnable() {
-            @Override
-            public void run() {
-                mActions.remove(action);
-            }
-        });
+        assertRunOnServiceThread();
+        mActions.remove(action);
     }
 
     // Remove all actions matched with the given Class type.
     private <T extends FeatureAction> void removeAction(final Class<T> clazz) {
-        runOnServiceThread(new Runnable() {
-            @Override
-            public void run() {
-                Iterator<FeatureAction> iter = mActions.iterator();
-                while (iter.hasNext()) {
-                    FeatureAction action = iter.next();
-                    if (action.getClass().equals(clazz)) {
-                        action.clear();
-                        mActions.remove(action);
-                    }
-                }
+        removeActionExcept(clazz, null);
+    }
+
+    // Remove all actions matched with the given Class type besides |exception|.
+    <T extends FeatureAction> void removeActionExcept(final Class<T> clazz,
+            final FeatureAction exception) {
+        assertRunOnServiceThread();
+        Iterator<FeatureAction> iter = mActions.iterator();
+        while (iter.hasNext()) {
+            FeatureAction action = iter.next();
+            if (action != exception && action.getClass().equals(clazz)) {
+                action.clear();
+                mActions.remove(action);
             }
-        });
+        }
     }
 
     private void runOnServiceThread(Runnable runnable) {
         mHandler.post(runnable);
     }
 
+    void runOnServiceThreadAtFrontOfQueue(Runnable runnable) {
+        mHandler.postAtFrontOfQueue(runnable);
+    }
+
+    private void assertRunOnServiceThread() {
+        if (Looper.myLooper() != mHandler.getLooper()) {
+            throw new IllegalStateException("Should run on service thread.");
+        }
+    }
+
     /**
      * Change ARC status into the given {@code enabled} status.
      *
@@ -306,8 +320,12 @@
             case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS:
                 handleReportPhysicalAddress(message);
                 return true;
-            // TODO: Add remaining system information query such as
-            // <Give Device Power Status> and <Request Active Source> handler.
+            case HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE:
+                handleSetSystemAudioMode(message);
+                return true;
+            case HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
+                handleSystemAudioModeStatus(message);
+                return true;
             default:
                 return dispatchMessageToAction(message);
         }
@@ -413,7 +431,7 @@
             sendCecCommand(
                     HdmiCecMessageBuilder.buildFeatureAbortCommand(message.getDestination(),
                             message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE,
-                            HdmiCecMessageBuilder.ABORT_UNRECOGNIZED_MODE));
+                            HdmiConstants.ABORT_UNRECOGNIZED_MODE));
             return;
         }
 
@@ -438,6 +456,33 @@
         return false;
     }
 
+    private void handleSetSystemAudioMode(HdmiCecMessage message) {
+        if (dispatchMessageToAction(message) || !isMessageForSystemAudio(message)) {
+            return;
+        }
+        SystemAudioActionFromAvr action = new SystemAudioActionFromAvr(this,
+                message.getDestination(), message.getSource(),
+                HdmiUtils.parseCommandParamSystemAudioStatus(message));
+        addAndStartAction(action);
+    }
+
+    private void handleSystemAudioModeStatus(HdmiCecMessage message) {
+        if (!isMessageForSystemAudio(message)) {
+            return;
+        }
+        setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message));
+    }
+
+    private boolean isMessageForSystemAudio(HdmiCecMessage message) {
+        if (message.getSource() != HdmiCec.ADDR_AUDIO_SYSTEM
+                || message.getDestination() != HdmiCec.ADDR_TV
+                || getAvrDeviceInfo() == null) {
+            Slog.w(TAG, "Skip abnormal CecMessage: " + message);
+            return false;
+        }
+        return true;
+    }
+
     // Record class that monitors the event of the caller of being killed. Used to clean up
     // the listener list and record list accordingly.
     private final class HotplugEventListenerRecord implements IBinder.DeathRecipient {
@@ -627,4 +672,32 @@
             Slog.e(TAG, "Invoking callback failed:" + e);
         }
     }
+
+    HdmiCecDeviceInfo getAvrDeviceInfo() {
+        return mCecController.getDeviceInfo(HdmiCec.ADDR_AUDIO_SYSTEM);
+    }
+
+    void setSystemAudioMode(boolean newMode) {
+        assertRunOnServiceThread();
+        if (newMode != mSystemAudioMode) {
+            // TODO: Need to set the preference for SystemAudioMode.
+            // TODO: Need to handle the notification of changing the mode and
+            // to identify the notification should be handled in the service or TvSettings.
+            mSystemAudioMode = newMode;
+        }
+    }
+
+    boolean getSystemAudioMode() {
+        assertRunOnServiceThread();
+        return mSystemAudioMode;
+    }
+
+    void setAudioStatus(boolean mute, int volume) {
+        // TODO: Hook up with AudioManager.
+    }
+
+    boolean isInPresetInstallationMode() {
+        // TODO: Implement this.
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
new file mode 100644
index 0000000..ef128ed1
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -0,0 +1,74 @@
+/*
+ * 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.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+/**
+ * Various utilities to handle HDMI CEC messages.
+ */
+final class HdmiUtils {
+
+    private HdmiUtils() { /* cannot be instantiated */ }
+
+    /**
+     * Verify if the given address is for the given device type.  If not it will throw
+     * {@link IllegalArgumentException}.
+     *
+     * @param logicalAddress the logical address to verify
+     * @param deviceType the device type to check
+     * @throw IllegalArgumentException
+     */
+    static void verifyAddressType(int logicalAddress, int deviceType) {
+        int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
+        if (actualDeviceType != deviceType) {
+            throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
+                    + ", Actual:" + actualDeviceType);
+        }
+    }
+
+    /**
+     * Check if the given CEC message come from the given address.
+     *
+     * @param cmd the CEC message to check
+     * @param expectedAddress the expected source address of the given message
+     * @param tag the tag of caller module (for log message)
+     * @return true if the CEC message comes from the given address
+     */
+    static boolean checkCommandSource(HdmiCecMessage cmd, int expectedAddress, String tag) {
+        int src = cmd.getSource();
+        if (src != expectedAddress) {
+            Slog.w(tag, "Invalid source [Expected:" + expectedAddress + ", Actual:" + src + "]");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Parse the parameter block of CEC message as [System Audio Status].
+     *
+     * @param cmd the CEC message to parse
+     * @return true if the given parameter has [ON] value
+     */
+    static boolean parseCommandParamSystemAudioStatus(HdmiCecMessage cmd) {
+        // TODO: Handle the exception when the length is wrong.
+        return cmd.getParams().length > 0
+                && cmd.getParams()[0] == HdmiConstants.SYSTEM_AUDIO_STATUS_ON;
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 05614a4..08ca306 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -44,28 +44,15 @@
      */
     RequestArcAction(HdmiControlService service, int sourceAddress, int avrAddress) {
         super(service, sourceAddress);
-        verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
-        verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+        HdmiUtils.verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+        HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
         mAvrAddress = avrAddress;
     }
 
-    private static void verifyAddressType(int logicalAddress, int deviceType) {
-        int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
-        if (actualDeviceType != deviceType) {
-            throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
-                    + ", Actual:" + actualDeviceType);
-        }
-    }
-
     @Override
     boolean processCommand(HdmiCecMessage cmd) {
-        if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
-            return false;
-        }
-
-        int src = cmd.getSource();
-        if (src != mAvrAddress) {
-            Slog.w(TAG, "Invalid source [Expected:" + mAvrAddress + ", Actual:" + src + "]");
+        if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE
+                || !HdmiUtils.checkCommandSource(cmd, mAvrAddress, TAG)) {
             return false;
         }
         int opcode = cmd.getOpcode();
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index e3525d8..d53d88d 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -46,21 +46,12 @@
     SetArcTransmissionStateAction(HdmiControlService service, int sourceAddress, int avrAddress,
             boolean enabled) {
         super(service, sourceAddress);
-        verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
-        verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+        HdmiUtils.verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+        HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
         mAvrAddress = avrAddress;
         mEnabled = enabled;
     }
 
-    // TODO: extract it as separate utility class.
-    private static void verifyAddressType(int logicalAddress, int deviceType) {
-        int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
-        if (actualDeviceType != deviceType) {
-            throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
-                    + ", Actual:" + actualDeviceType);
-        }
-    }
-
     @Override
     boolean start() {
         if (mEnabled) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
new file mode 100644
index 0000000..dde3342
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -0,0 +1,192 @@
+/*
+ * 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.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+
+/**
+ * Base feature action class for SystemAudioActionFromTv and SystemAudioActionFromAvr.
+ */
+abstract class SystemAudioAction extends FeatureAction {
+    private static final String TAG = "SystemAudioAction";
+
+    // State in which waits for <SetSystemAudioMode>.
+    private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 1;
+
+    // State in which waits for <ReportAudioStatus>.
+    private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 2;
+
+    private static final int MAX_SEND_RETRY_COUNT = 2;
+
+    private static final int ON_TIMEOUT_MS = 5000;
+    private static final int OFF_TIMEOUT_MS = TIMEOUT_MS;
+
+    // Logical address of AV Receiver.
+    protected final int mAvrLogicalAddress;
+
+    // The target audio status of the action, whether to enable the system audio mode or not.
+    protected boolean mTargetAudioStatus;
+
+    private int mSendRetryCount = 0;
+
+    /**
+     * Constructor
+     *
+     * @param service {@link HdmiControlService} instance
+     * @param sourceAddress logical address of source device (TV or STB).
+     * @param avrAddress logical address of AVR device
+     * @param targetStatus Whether to enable the system audio mode or not
+     * @throw IllegalArugmentException if device type of sourceAddress and avrAddress is invalid
+     */
+    SystemAudioAction(HdmiControlService service, int sourceAddress, int avrAddress,
+            boolean targetStatus) {
+        super(service, sourceAddress);
+        HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+        mAvrLogicalAddress = avrAddress;
+        mTargetAudioStatus = targetStatus;
+    }
+
+    protected void sendSystemAudioModeRequest() {
+        int avrPhysicalAddress = mService.getAvrDeviceInfo().getPhysicalAddress();
+        HdmiCecMessage command = HdmiCecMessageBuilder.buildSystemAudioModeRequest(mSourceAddress,
+                mAvrLogicalAddress, avrPhysicalAddress, mTargetAudioStatus);
+        sendCommand(command, new HdmiControlService.SendMessageCallback() {
+            @Override
+            public void onSendCompleted(int error) {
+                if (error == HdmiControlService.SEND_RESULT_SUCCESS) {
+                    mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
+                    addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
+                } else {
+                    setSystemAudioMode(false);
+                    finish();
+                }
+            }
+        });
+    }
+
+    private void handleSendSystemAudioModeRequestTimeout() {
+        if (!mTargetAudioStatus  // Don't retry for Off case.
+                || mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
+            setSystemAudioMode(false);
+            finish();
+            return;
+        }
+        sendSystemAudioModeRequest();
+    }
+
+    protected void setSystemAudioMode(boolean mode) {
+        mService.setSystemAudioMode(mode);
+    }
+
+    protected void sendGiveAudioStatus() {
+        HdmiCecMessage command = HdmiCecMessageBuilder.buildGiveAudioStatus(mSourceAddress,
+                mAvrLogicalAddress);
+        sendCommand(command, new HdmiControlService.SendMessageCallback() {
+            @Override
+            public void onSendCompleted(int error) {
+                if (error == HdmiControlService.SEND_RESULT_SUCCESS) {
+                    mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS;
+                    addTimer(mState, TIMEOUT_MS);
+                } else {
+                    handleSendGiveAudioStatusFailure();
+                }
+            }
+        });
+    }
+
+    private void handleSendGiveAudioStatusFailure() {
+        // TODO: Notify the failure status.
+
+        int uiCommand = mService.getSystemAudioMode()
+                ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION  // SystemAudioMode: ON
+                : HdmiConstants.UI_COMMAND_MUTE_FUNCTION;           // SystemAudioMode: OFF
+        sendUserControlPressedAndReleased(uiCommand);
+        finish();
+    }
+
+    private void sendUserControlPressedAndReleased(int uiCommand) {
+        sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(
+                mSourceAddress, mAvrLogicalAddress, uiCommand));
+        sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
+                mSourceAddress, mAvrLogicalAddress));
+    }
+
+    @Override
+    final boolean processCommand(HdmiCecMessage cmd) {
+        switch (mState) {
+            case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
+                // TODO: Handle <FeatureAbort> of <SystemAudioModeRequest>
+                if (cmd.getOpcode() != HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE
+                        || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) {
+                    return false;
+                }
+                boolean receivedStatus = HdmiUtils.parseCommandParamSystemAudioStatus(cmd);
+                if (receivedStatus == mTargetAudioStatus) {
+                    setSystemAudioMode(receivedStatus);
+                    sendGiveAudioStatus();
+                } else {
+                    // Unexpected response, consider the request is newly initiated by AVR.
+                    // To return 'false' will initiate new SystemAudioActionFromAvr by the control
+                    // service.
+                    finish();
+                    return false;
+                }
+                return true;
+
+            case STATE_WAIT_FOR_REPORT_AUDIO_STATUS:
+                // TODO: Handle <FeatureAbort> of <GiveAudioStatus>
+                if (cmd.getOpcode() != HdmiCec.MESSAGE_REPORT_AUDIO_STATUS
+                        || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) {
+                    return false;
+                }
+                byte[] params = cmd.getParams();
+                if (params.length > 0) {
+                    boolean mute = (params[0] & 0x80) == 0x80;
+                    int volume = params[0] & 0x7F;
+                    mService.setAudioStatus(mute, volume);
+                    if (mTargetAudioStatus && mute || !mTargetAudioStatus && !mute) {
+                        // Toggle AVR's mute status to match with the system audio status.
+                        sendUserControlPressedAndReleased(HdmiConstants.UI_COMMAND_MUTE);
+                    }
+                }
+                finish();
+                return true;
+        }
+        return false;
+    }
+
+    protected void removeSystemAudioActionInProgress() {
+        mService.removeActionExcept(SystemAudioActionFromTv.class, this);
+        mService.removeActionExcept(SystemAudioActionFromAvr.class, this);
+    }
+
+    @Override
+    final void handleTimerEvent(int state) {
+        if (mState != state) {
+            return;
+        }
+        switch (mState) {
+            case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
+                handleSendSystemAudioModeRequestTimeout();
+                return;
+            case STATE_WAIT_FOR_REPORT_AUDIO_STATUS:
+                handleSendGiveAudioStatusFailure();
+                return;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
new file mode 100644
index 0000000..c5eb44b
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
@@ -0,0 +1,69 @@
+/*
+ * 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.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+
+/**
+ * Feature action that handles System Audio initiated by AVR devices.
+ */
+final class SystemAudioActionFromAvr extends SystemAudioAction {
+    /**
+     * Constructor
+     *
+     * @param service {@link HdmiControlService} instance
+     * @param tvAddress logical address of TV device
+     * @param avrAddress logical address of AVR device
+     * @param targetStatus Whether to enable the system audio mode or not
+     * @throw IllegalArugmentException if device type of tvAddress and avrAddress is invalid
+     */
+    SystemAudioActionFromAvr(HdmiControlService service, int tvAddress, int avrAddress,
+            boolean targetStatus) {
+        super(service, tvAddress, avrAddress, targetStatus);
+        HdmiUtils.verifyAddressType(tvAddress, HdmiCec.DEVICE_TV);
+    }
+
+    @Override
+    boolean start() {
+        removeSystemAudioActionInProgress();
+        handleSystemAudioActionFromAvr();
+        return true;
+    }
+
+    private void handleSystemAudioActionFromAvr() {
+        if (mTargetAudioStatus == mService.getSystemAudioMode()) {
+            finish();
+            return;
+        }
+        if (mService.isInPresetInstallationMode()) {
+            sendCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                    mSourceAddress, mAvrLogicalAddress,
+                    HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE, HdmiConstants.ABORT_REFUSED));
+            mTargetAudioStatus = false;
+            sendSystemAudioModeRequest();
+            return;
+        }
+        // TODO: Stop the action for System Audio Mode initialization if it is running.
+        if (mTargetAudioStatus) {
+            setSystemAudioMode(true);
+            sendGiveAudioStatus();
+        } else {
+            setSystemAudioMode(false);
+            finish();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
new file mode 100644
index 0000000..9994de6
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
@@ -0,0 +1,50 @@
+/*
+ * 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.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+
+
+/**
+ * Feature action that handles System Audio initiated by TV devices.
+ */
+final class SystemAudioActionFromTv extends SystemAudioAction {
+    /**
+     * Constructor
+     *
+     * @param service {@link HdmiControlService} instance
+     * @param tvAddress logical address of TV device
+     * @param avrAddress logical address of AVR device
+     * @param targetStatus Whether to enable the system audio mode or not
+     * @throw IllegalArugmentException if device type of tvAddress is invalid
+     */
+    SystemAudioActionFromTv(HdmiControlService service, int tvAddress, int avrAddress,
+            boolean targetStatus) {
+        super(service, tvAddress, avrAddress, targetStatus);
+        HdmiUtils.verifyAddressType(tvAddress, HdmiCec.DEVICE_TV);
+    }
+
+    @Override
+    boolean start() {
+        // TODO: Check HDMI-CEC is enabled.
+        // TODO: Move to the waiting state if currently a routing change is in progress.
+
+        removeSystemAudioActionInProgress();
+        sendSystemAudioModeRequest();
+        return true;
+    }
+}
diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
index 51ee93b..2699fea 100644
--- a/services/core/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java
@@ -96,7 +96,7 @@
                 Looper.myLooper());
     }
 
-    public boolean isSupported() {
+    public static boolean isSupported() {
         return nativeIsSupported();
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index c909a54..737ffda 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -25,6 +25,7 @@
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
 import android.media.session.MediaController;
+import android.media.session.RemoteVolumeProvider;
 import android.media.session.RouteCommand;
 import android.media.session.RouteInfo;
 import android.media.session.RouteOptions;
@@ -33,6 +34,7 @@
 import android.media.session.MediaSessionInfo;
 import android.media.session.RouteInterface;
 import android.media.session.PlaybackState;
+import android.media.AudioManager;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.os.Bundle;
@@ -112,6 +114,14 @@
     private long mLastActiveTime;
     // End TransportPerformer fields
 
+    // Volume handling fields
+    private int mPlaybackType = MediaSession.VOLUME_TYPE_LOCAL;
+    private int mAudioStream = AudioManager.STREAM_MUSIC;
+    private int mVolumeControlType = RemoteVolumeProvider.VOLUME_CONTROL_ABSOLUTE;
+    private int mMaxVolume = 0;
+    private int mCurrentVolume = 0;
+    // End volume handling fields
+
     private boolean mIsActive = false;
     private boolean mDestroyed = false;
 
@@ -248,6 +258,27 @@
     }
 
     /**
+     * Send a volume adjustment to the session owner.
+     *
+     * @param delta The amount to adjust the volume by.
+     */
+    public void adjustVolumeBy(int delta) {
+        if (mVolumeControlType == RemoteVolumeProvider.VOLUME_CONTROL_FIXED) {
+            // Nothing to do, the volume cannot be changed
+            return;
+        }
+        mSessionCb.adjustVolumeBy(delta);
+    }
+
+    public void setVolumeTo(int value) {
+        if (mVolumeControlType != RemoteVolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
+            // Nothing to do. The volume can't be set directly.
+            return;
+        }
+        mSessionCb.setVolumeTo(value);
+    }
+
+    /**
      * Set the connection to use for the selected route and notify the app it is
      * now connected.
      *
@@ -294,14 +325,16 @@
      * Check if the session is currently performing playback. This will also
      * return true if the session was recently paused.
      *
+     * @param includeRecentlyActive True if playback that was recently paused
+     *            should count, false if it shouldn't.
      * @return True if the session is performing playback, false otherwise.
      */
-    public boolean isPlaybackActive() {
+    public boolean isPlaybackActive(boolean includeRecentlyActive) {
         int state = mPlaybackState == null ? 0 : mPlaybackState.getState();
         if (isActiveState(state)) {
             return true;
         }
-        if (state == mPlaybackState.STATE_PAUSED) {
+        if (includeRecentlyActive && state == mPlaybackState.STATE_PAUSED) {
             long inactiveTime = SystemClock.uptimeMillis() - mLastActiveTime;
             if (inactiveTime < ACTIVE_BUFFER) {
                 return true;
@@ -311,6 +344,54 @@
     }
 
     /**
+     * Get the type of playback, either local or remote.
+     *
+     * @return The current type of playback.
+     */
+    public int getPlaybackType() {
+        return mPlaybackType;
+    }
+
+    /**
+     * Get the local audio stream being used. Only valid if playback type is
+     * local.
+     *
+     * @return The audio stream the session is using.
+     */
+    public int getAudioStream() {
+        return mAudioStream;
+    }
+
+    /**
+     * Get the type of volume control. Only valid if playback type is remote.
+     *
+     * @return The volume control type being used.
+     */
+    public int getVolumeControl() {
+        return mVolumeControlType;
+    }
+
+    /**
+     * Get the max volume that can be set. Only valid if playback type is
+     * remote.
+     *
+     * @return The max volume that can be set.
+     */
+    public int getMaxVolume() {
+        return mMaxVolume;
+    }
+
+    /**
+     * Get the current volume for this session. Only valid if playback type is
+     * remote.
+     *
+     * @return The current volume of the remote playback.
+     */
+    public int getCurrentVolume() {
+        return mCurrentVolume;
+    }
+
+    /**
      * @return True if this session is currently connected to a route.
      */
     public boolean isConnected() {
@@ -640,6 +721,40 @@
                 mRequests.add(request);
             }
         }
+
+        @Override
+        public void setCurrentVolume(int volume) {
+            mCurrentVolume = volume;
+        }
+
+        @Override
+        public void configureVolumeHandling(int type, int arg1, int arg2) throws RemoteException {
+            switch(type) {
+                case MediaSession.VOLUME_TYPE_LOCAL:
+                    mPlaybackType = type;
+                    int audioStream = arg1;
+                    if (isValidStream(audioStream)) {
+                        mAudioStream = audioStream;
+                    } else {
+                        Log.e(TAG, "Cannot set stream to " + audioStream + ". Using music stream");
+                        mAudioStream = AudioManager.STREAM_MUSIC;
+                    }
+                    break;
+                case MediaSession.VOLUME_TYPE_REMOTE:
+                    mPlaybackType = type;
+                    mVolumeControlType = arg1;
+                    mMaxVolume = arg2;
+                    break;
+                default:
+                    throw new IllegalArgumentException("Volume handling type " + type
+                            + " not recognized.");
+            }
+        }
+
+        private boolean isValidStream(int stream) {
+            return stream >= AudioManager.STREAM_VOICE_CALL
+                    && stream <= AudioManager.STREAM_NOTIFICATION;
+        }
     }
 
     class SessionCb {
@@ -780,6 +895,22 @@
                 Slog.e(TAG, "Remote failure in rate.", e);
             }
         }
+
+        public void adjustVolumeBy(int delta) {
+            try {
+                mCb.onAdjustVolumeBy(delta);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in adjustVolumeBy.", e);
+            }
+        }
+
+        public void setVolumeTo(int value) {
+            try {
+                mCb.onSetVolumeTo(value);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in adjustVolumeBy.", e);
+            }
+        }
     }
 
     class ControllerStub extends ISessionController.Stub {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 9d85167..87665e1 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -26,6 +26,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.media.IAudioService;
 import android.media.routeprovider.RouteRequest;
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
@@ -40,6 +42,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.speech.RecognizerIntent;
@@ -79,6 +82,7 @@
     private final PowerManager.WakeLock mMediaEventWakeLock;
 
     private KeyguardManager mKeyguardManager;
+    private IAudioService mAudioService;
 
     private MediaSessionRecord mPrioritySession;
     private int mCurrentUserId = -1;
@@ -105,6 +109,12 @@
         updateUser();
         mKeyguardManager =
                 (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
+        mAudioService = getAudioService();
+    }
+
+    private IAudioService getAudioService() {
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        return IAudioService.Stub.asInterface(b);
     }
 
     /**
@@ -703,6 +713,23 @@
         }
 
         @Override
+        public void dispatchAdjustVolumeBy(int suggestedStream, int delta, int flags)
+                throws RemoteException {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    MediaSessionRecord session = mPriorityStack
+                            .getDefaultVolumeSession(mCurrentUserId);
+                    dispatchAdjustVolumeByLocked(suggestedStream, delta, flags, session);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -737,6 +764,49 @@
             }
         }
 
+        private void dispatchAdjustVolumeByLocked(int suggestedStream, int delta, int flags,
+                MediaSessionRecord session) {
+            int direction = 0;
+            int steps = delta;
+            if (delta > 0) {
+                direction = 1;
+            } else if (delta < 0) {
+                direction = -1;
+                steps = -delta;
+            }
+            if (DEBUG) {
+                String sessionInfo = session == null ? null : session.getSessionInfo().toString();
+                Log.d(TAG, "Adjusting session " + sessionInfo + " by " + delta + ". flags=" + flags
+                        + ", suggestedStream=" + suggestedStream);
+
+            }
+            if (session == null) {
+                for (int i = 0; i < steps; i++) {
+                    try {
+                        mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
+                                flags, getContext().getOpPackageName());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error adjusting default volume.", e);
+                    }
+                }
+            } else {
+                if (session.getPlaybackType() == MediaSession.VOLUME_TYPE_LOCAL) {
+                    for (int i = 0; i < steps; i++) {
+                        try {
+                            mAudioService.adjustSuggestedStreamVolume(direction,
+                                    session.getAudioStream(), flags,
+                                    getContext().getOpPackageName());
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error adjusting volume for stream "
+                                    + session.getAudioStream(), e);
+                        }
+                    }
+                } else if (session.getPlaybackType() == MediaSession.VOLUME_TYPE_REMOTE) {
+                    session.adjustVolumeBy(delta);
+                }
+            }
+        }
+
         private void handleVoiceKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock,
                 MediaSessionRecord session) {
             if (session != null && session.hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 56236f8..803dee2 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -52,6 +52,7 @@
 
     private MediaSessionRecord mCachedButtonReceiver;
     private MediaSessionRecord mCachedDefault;
+    private MediaSessionRecord mCachedVolumeDefault;
     private ArrayList<MediaSessionRecord> mCachedActiveList;
     private ArrayList<MediaSessionRecord> mCachedTransportControlList;
 
@@ -93,6 +94,9 @@
             mSessions.remove(record);
             mSessions.add(0, record);
             clearCache();
+        } else if (newState == PlaybackState.STATE_PAUSED) {
+            // Just clear the volume cache in this case
+            mCachedVolumeDefault = null;
         }
     }
 
@@ -177,6 +181,25 @@
         return mCachedButtonReceiver;
     }
 
+    public MediaSessionRecord getDefaultVolumeSession(int userId) {
+        if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
+            return mGlobalPrioritySession;
+        }
+        if (mCachedVolumeDefault != null) {
+            return mCachedVolumeDefault;
+        }
+        ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);
+        int size = records.size();
+        for (int i = 0; i < size; i++) {
+            MediaSessionRecord record = records.get(i);
+            if (record.isPlaybackActive(false)) {
+                mCachedVolumeDefault = record;
+                return record;
+            }
+        }
+        return null;
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         ArrayList<MediaSessionRecord> sortedSessions = getPriorityListLocked(false, 0,
                 UserHandle.USER_ALL);
@@ -237,7 +260,7 @@
                 lastLocalIndex++;
                 lastActiveIndex++;
                 lastPublishedIndex++;
-            } else if (session.isPlaybackActive()) {
+            } else if (session.isPlaybackActive(true)) {
                 // TODO replace getRoute() == null with real local route check
                 if(session.getRoute() == null) {
                     // Active local sessions get top priority
@@ -284,6 +307,7 @@
 
     private void clearCache() {
         mCachedDefault = null;
+        mCachedVolumeDefault = null;
         mCachedButtonReceiver = null;
         mCachedActiveList = null;
         mCachedTransportControlList = null;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 13cc98c..bb93663 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -40,6 +40,7 @@
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.content.NativeLibraryHelper.ApkHandle;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
@@ -4148,7 +4149,7 @@
                 continue;
             }
             PackageParser.Package pkg = scanPackageLI(file,
-                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
+                    flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null, null);
             // Don't mess around with apps in system partition.
             if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
                     mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
@@ -4215,7 +4216,7 @@
      *  Returns null in case of errors and the error code is stored in mLastScanError
      */
     private PackageParser.Package scanPackageLI(File scanFile,
-            int parseFlags, int scanMode, long currentTime, UserHandle user) {
+            int parseFlags, int scanMode, long currentTime, UserHandle user, String abiOverride) {
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         String scanPath = scanFile.getPath();
         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanPath);
@@ -4283,7 +4284,7 @@
                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
                     return null;
                 } else {
-                    // The current app on the system partion is better than
+                    // The current app on the system partition is better than
                     // what we have updated to on the data partition; switch
                     // back to the system partition version.
                     // At this point, its safely assumed that package installation for
@@ -4402,7 +4403,7 @@
         setApplicationInfoPaths(pkg, codePath, resPath);
         // Note that we invoke the following method only if we are about to unpack an application
         PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
-                | SCAN_UPDATE_SIGNATURE, currentTime, user);
+                | SCAN_UPDATE_SIGNATURE, currentTime, user, abiOverride);
 
         /*
          * If the system app should be overridden by a previously installed
@@ -4945,7 +4946,7 @@
     }
 
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
-            int parseFlags, int scanMode, long currentTime, UserHandle user) {
+            int parseFlags, int scanMode, long currentTime, UserHandle user, String abiOverride) {
         File scanFile = new File(pkg.mScanPath);
         if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
                 pkg.applicationInfo.publicSourceDir == null) {
@@ -5395,7 +5396,22 @@
          *        only for non-system apps and system app upgrades.
          */
         if (pkg.applicationInfo.nativeLibraryDir != null) {
+            final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
             try {
+                // Enable gross and lame hacks for apps that are built with old
+                // SDK tools. We must scan their APKs for renderscript bitcode and
+                // not launch them if it's present. Don't bother checking on devices
+                // that don't have 64 bit support.
+                String[] abiList = Build.SUPPORTED_ABIS;
+                boolean hasLegacyRenderscriptBitcode = false;
+                if (abiOverride != null) {
+                    abiList = new String[] { abiOverride };
+                } else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
+                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+                    abiList = Build.SUPPORTED_32_BIT_ABIS;
+                    hasLegacyRenderscriptBitcode = true;
+                }
+
                 File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
                 final String dataPathString = dataPath.getCanonicalPath();
 
@@ -5411,21 +5427,26 @@
                         Log.i(TAG, "removed obsolete native libraries for system package "
                                 + path);
                     }
-
-                    setInternalAppAbi(pkg, pkgSetting);
+                    if (abiOverride != null || hasLegacyRenderscriptBitcode) {
+                        pkg.applicationInfo.cpuAbi = abiList[0];
+                        pkgSetting.cpuAbiString = abiList[0];
+                    } else {
+                        setInternalAppAbi(pkg, pkgSetting);
+                    }
                 } else {
                     if (!isForwardLocked(pkg) && !isExternal(pkg)) {
                         /*
-                         * Update native library dir if it starts with
-                         * /data/data
-                         */
+                        * Update native library dir if it starts with
+                        * /data/data
+                        */
                         if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
                             setInternalAppNativeLibraryPath(pkg, pkgSetting);
                             nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
                         }
 
                         try {
-                            int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir);
+                            int copyRet = copyNativeLibrariesForInternalApp(handle,
+                                    nativeLibraryDir, abiList);
                             if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
                                 Slog.e(TAG, "Unable to copy native libraries");
                                 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -5435,7 +5456,9 @@
                             // We've successfully copied native libraries across, so we make a
                             // note of what ABI we're using
                             if (copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
-                                pkg.applicationInfo.cpuAbi = Build.SUPPORTED_ABIS[copyRet];
+                                pkg.applicationInfo.cpuAbi = abiList[copyRet];
+                            } else if (abiOverride != null || hasLegacyRenderscriptBitcode) {
+                                pkg.applicationInfo.cpuAbi = abiList[0];
                             } else {
                                 pkg.applicationInfo.cpuAbi = null;
                             }
@@ -5452,20 +5475,22 @@
                         // to clean this up but we'll need to change the interface between this service
                         // and IMediaContainerService (but doing so will spread this logic out, rather
                         // than centralizing it).
-                        final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
-                        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+                        final int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
                         if (abi >= 0) {
-                            pkg.applicationInfo.cpuAbi = Build.SUPPORTED_ABIS[abi];
+                            pkg.applicationInfo.cpuAbi = abiList[abi];
                         } else if (abi == PackageManager.NO_NATIVE_LIBRARIES) {
                             // Note that (non upgraded) system apps will not have any native
                             // libraries bundled in their APK, but we're guaranteed not to be
                             // such an app at this point.
-                            pkg.applicationInfo.cpuAbi = null;
+                            if (abiOverride != null || hasLegacyRenderscriptBitcode) {
+                                pkg.applicationInfo.cpuAbi = abiList[0];
+                            } else {
+                                pkg.applicationInfo.cpuAbi = null;
+                            }
                         } else {
                             mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                             return null;
                         }
-                        handle.close();
                     }
 
                     if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
@@ -5482,8 +5507,12 @@
                         }
                     }
                 }
+
+                pkgSetting.cpuAbiString = pkg.applicationInfo.cpuAbi;
             } catch (IOException ioe) {
                 Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
+            } finally {
+                handle.close();
             }
         }
         pkg.mScanPath = path;
@@ -6175,8 +6204,8 @@
         }
     }
 
-    private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
-            throws IOException {
+    private static int copyNativeLibrariesForInternalApp(ApkHandle handle,
+            final File nativeLibraryDir, String[] abiList) throws IOException {
         if (!nativeLibraryDir.isDirectory()) {
             nativeLibraryDir.delete();
 
@@ -6198,21 +6227,16 @@
          * If this is an internal application or our nativeLibraryPath points to
          * the app-lib directory, unpack the libraries if necessary.
          */
-        final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
-        try {
-            int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
-            if (abi >= 0) {
-                int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
-                        nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
-                if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
-                    return copyRet;
-                }
+        int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
+        if (abi >= 0) {
+            int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+                    nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
+            if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+                return copyRet;
             }
-
-            return abi;
-        } finally {
-            handle.close();
         }
+
+        return abi;
     }
 
     private void killApplication(String pkgName, int appId, String reason) {
@@ -7536,7 +7560,7 @@
                         }
                         p = scanPackageLI(fullPath, flags,
                                 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
-                                System.currentTimeMillis(), UserHandle.ALL);
+                                System.currentTimeMillis(), UserHandle.ALL, null);
                         if (p != null) {
                             /*
                              * TODO this seems dangerous as the package may have
@@ -7657,6 +7681,16 @@
         if (observer == null && observer2 == null) {
             throw new IllegalArgumentException("No install observer supplied");
         }
+        installPackageWithVerificationEncryptionAndAbiOverrideEtc(packageURI, observer, observer2,
+                flags, installerPackageName, verificationParams, encryptionParams, null);
+    }
+
+    @Override
+    public void installPackageWithVerificationEncryptionAndAbiOverrideEtc(Uri packageURI,
+            IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+            int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams,
+            String packageAbiOverride) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
                 null);
 
@@ -7696,7 +7730,8 @@
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(packageURI, observer, observer2, filteredFlags,
-                installerPackageName, verificationParams, encryptionParams, user);
+                installerPackageName, verificationParams, encryptionParams, user,
+                packageAbiOverride);
         mHandler.sendMessage(msg);
     }
 
@@ -8405,11 +8440,14 @@
         private int mRet;
         private File mTempPackage;
         final ContainerEncryptionParams encryptionParams;
+        final String packageAbiOverride;
+        final String packageInstructionSetOverride;
 
         InstallParams(Uri packageURI,
                 IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
                 int flags, String installerPackageName, VerificationParams verificationParams,
-                ContainerEncryptionParams encryptionParams, UserHandle user) {
+                ContainerEncryptionParams encryptionParams, UserHandle user,
+                String packageAbiOverride) {
             super(user);
             this.mPackageURI = packageURI;
             this.flags = flags;
@@ -8418,6 +8456,9 @@
             this.installerPackageName = installerPackageName;
             this.verificationParams = verificationParams;
             this.encryptionParams = encryptionParams;
+            this.packageAbiOverride = packageAbiOverride;
+            this.packageInstructionSetOverride = (packageAbiOverride == null) ?
+                    packageAbiOverride : VMRuntime.getInstructionSet(packageAbiOverride);
         }
 
         @Override
@@ -8563,7 +8604,7 @@
                         // Remote call to find out default install location
                         final String packageFilePath = packageFile.getAbsolutePath();
                         pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
-                                lowThreshold);
+                                lowThreshold, packageAbiOverride);
 
                         /*
                          * If we have too little free space, try to free cache
@@ -8572,10 +8613,10 @@
                         if (pkgLite.recommendedInstallLocation
                                 == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                             final long size = mContainerService.calculateInstalledSize(
-                                    packageFilePath, isForwardLocked());
+                                    packageFilePath, isForwardLocked(), packageAbiOverride);
                             if (mInstaller.freeCache(size + lowThreshold) >= 0) {
                                 pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
-                                        flags, lowThreshold);
+                                        flags, lowThreshold, packageAbiOverride);
                             }
                             /*
                              * The cache free must have deleted the file we
@@ -8995,11 +9036,12 @@
         final ManifestDigest manifestDigest;
         final UserHandle user;
         final String instructionSet;
+        final String abiOverride;
 
         InstallArgs(Uri packageURI,
                 IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
                 int flags, String installerPackageName, ManifestDigest manifestDigest,
-                UserHandle user, String instructionSet) {
+                UserHandle user, String instructionSet, String abiOverride) {
             this.packageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
@@ -9008,6 +9050,7 @@
             this.manifestDigest = manifestDigest;
             this.user = user;
             this.instructionSet = instructionSet;
+            this.abiOverride = abiOverride;
         }
 
         abstract void createCopyFile();
@@ -9063,12 +9106,13 @@
         FileInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.observer2, params.flags,
                     params.installerPackageName, params.getManifestDigest(),
-                    params.getUser(), null /* instruction set */);
+                    params.getUser(), params.packageInstructionSetOverride,
+                    params.packageAbiOverride);
         }
 
         FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
                 String instructionSet) {
-            super(null, null, null, 0, null, null, null, instructionSet);
+            super(null, null, null, 0, null, null, null, instructionSet, null);
             File codeFile = new File(fullCodePath);
             installDir = codeFile.getParentFile();
             codeFileName = fullCodePath;
@@ -9077,7 +9121,7 @@
         }
 
         FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) {
-            super(packageURI, null, null, 0, null, null, null, instructionSet);
+            super(packageURI, null, null, 0, null, null, null, instructionSet, null);
             installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
             String apkName = getNextCodePath(null, pkgName, ".apk");
             codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -9181,14 +9225,26 @@
                 NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
                 nativeLibraryFile.delete();
             }
+
+            final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codeFile);
+            String[] abiList = (abiOverride != null) ?
+                    new String[] { abiOverride } : Build.SUPPORTED_ABIS;
             try {
-                int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
+                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
+                        abiOverride == null &&
+                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+                    abiList = Build.SUPPORTED_32_BIT_ABIS;
+                }
+
+                int copyRet = copyNativeLibrariesForInternalApp(handle, nativeLibraryFile, abiList);
                 if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
                     return copyRet;
                 }
             } catch (IOException e) {
                 Slog.e(TAG, "Copying native libraries failed", e);
                 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+            } finally {
+                handle.close();
             }
 
             return ret;
@@ -9403,14 +9459,15 @@
         AsecInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.observer2, params.flags,
                     params.installerPackageName, params.getManifestDigest(),
-                    params.getUser(), null /* instruction set */);
+                    params.getUser(), params.packageInstructionSetOverride,
+                    params.packageAbiOverride);
         }
 
         AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
                 String instructionSet, boolean isExternal, boolean isForwardLocked) {
             super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
-                    null, null, null, instructionSet);
+                    null, null, null, instructionSet, null);
             // Extract cid from fullCodePath
             int eidx = fullCodePath.lastIndexOf("/");
             String subStr1 = fullCodePath.substring(0, eidx);
@@ -9422,7 +9479,7 @@
         AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) {
             super(null, null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
-                    null, null, null, instructionSet);
+                    null, null, null, instructionSet, null);
             this.cid = cid;
             setCachePath(PackageHelper.getSdDir(cid));
         }
@@ -9431,7 +9488,7 @@
                 boolean isExternal, boolean isForwardLocked) {
             super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
-                    null, null, null, instructionSet);
+                    null, null, null, instructionSet, null);
             this.cid = cid;
         }
 
@@ -9443,7 +9500,7 @@
             try {
                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
+                return imcs.checkExternalFreeStorage(packageURI, isFwdLocked(), abiOverride);
             } finally {
                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
             }
@@ -9469,7 +9526,8 @@
                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
-                        RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
+                        RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked(),
+                        abiOverride);
             } finally {
                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
             }
@@ -9777,7 +9835,7 @@
      */
     private void installNewPackageLI(PackageParser.Package pkg,
             int parseFlags, int scanMode, UserHandle user,
-            String installerPackageName, PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
         // Remember this for later, in case we need to rollback this install
         String pkgName = pkg.packageName;
 
@@ -9805,7 +9863,7 @@
         }
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
-                System.currentTimeMillis(), user);
+                System.currentTimeMillis(), user, abiOverride);
         if (newPackage == null) {
             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -9832,7 +9890,7 @@
 
     private void replacePackageLI(PackageParser.Package pkg,
             int parseFlags, int scanMode, UserHandle user,
-            String installerPackageName, PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
 
         PackageParser.Package oldPackage;
         String pkgName = pkg.packageName;
@@ -9861,17 +9919,19 @@
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
             replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
-                    user, allUsers, perUserInstalled, installerPackageName, res);
+                    user, allUsers, perUserInstalled, installerPackageName, res,
+                    abiOverride);
         } else {
             replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
-                    user, allUsers, perUserInstalled, installerPackageName, res);
+                    user, allUsers, perUserInstalled, installerPackageName, res,
+                    abiOverride);
         }
     }
 
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
             int[] allUsers, boolean[] perUserInstalled,
-            String installerPackageName, PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
         PackageParser.Package newPackage = null;
         String pkgName = deletedPackage.packageName;
         boolean deletedPkg = true;
@@ -9896,7 +9956,7 @@
             // Successfully deleted the old package. Now proceed with re-installation
             mLastScanError = PackageManager.INSTALL_SUCCEEDED;
             newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
-                    System.currentTimeMillis(), user);
+                    System.currentTimeMillis(), user, abiOverride);
             if (newPackage == null) {
                 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
                 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -9925,7 +9985,7 @@
             }
             // Since we failed to install the new package we need to restore the old
             // package that we deleted.
-            if(deletedPkg) {
+            if (deletedPkg) {
                 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
                 File restoreFile = new File(deletedPackage.mPath);
                 // Parse old package
@@ -9936,7 +9996,7 @@
                 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
                         | SCAN_UPDATE_TIME;
                 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
-                        origUpdateTime, null) == null) {
+                        origUpdateTime, null, null) == null) {
                     Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
                     return;
                 }
@@ -9956,7 +10016,7 @@
     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
             int[] allUsers, boolean[] perUserInstalled,
-            String installerPackageName, PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                 + ", old=" + deletedPackage);
         PackageParser.Package newPackage = null;
@@ -10010,7 +10070,7 @@
         // Successfully disabled the old package. Now proceed with re-installation
         res.returnCode = mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
-        newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
+        newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user, abiOverride);
         if (newPackage == null) {
             Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -10044,7 +10104,7 @@
                 removeInstalledPackageLI(newPackage, true);
             }
             // Add back the old system package
-            scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
+            scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user, null);
             // Restore the old system information in Settings
             synchronized(mPackages) {
                 if (updatedSettings) {
@@ -10278,10 +10338,10 @@
         pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
         if (replace) {
             replacePackageLI(pkg, parseFlags, scanMode, args.user,
-                    installerPackageName, res);
+                    installerPackageName, res, args.abiOverride);
         } else {
             installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,
-                    installerPackageName, res);
+                    installerPackageName, res, args.abiOverride);
         }
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -10698,7 +10758,7 @@
             parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
         }
         PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
-                parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
+                parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null, null);
 
         if (newPkg == null) {
             Slog.w(TAG, "Failed to restore system package:" + newPs.name
@@ -12511,7 +12571,7 @@
                 doGc = true;
                 synchronized (mInstallLock) {
                     final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
-                            0, 0, null);
+                            0, 0, null, null);
                     // Scan the package
                     if (pkg != null) {
                         /*
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 4bdd2be..34168a8 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -16,10 +16,10 @@
 
 package com.android.server.tv;
 
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvStreamConfig;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvStreamConfig;
 import android.view.Surface;
 
 /**
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index b95b0f0..e34f42b 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -17,12 +17,12 @@
 package com.android.server.tv;
 
 import android.content.Context;
+import android.media.tv.ITvInputHardware;
+import android.media.tv.ITvInputHardwareCallback;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvStreamConfig;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.tv.ITvInputHardware;
-import android.tv.ITvInputHardwareCallback;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvStreamConfig;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.KeyEvent;
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e52f218..5eb3305 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -31,6 +31,18 @@
 import android.content.pm.ServiceInfo;
 import android.database.Cursor;
 import android.graphics.Rect;
+import android.media.tv.ITvInputClient;
+import android.media.tv.ITvInputHardware;
+import android.media.tv.ITvInputHardwareCallback;
+import android.media.tv.ITvInputManager;
+import android.media.tv.ITvInputService;
+import android.media.tv.ITvInputServiceCallback;
+import android.media.tv.ITvInputSession;
+import android.media.tv.ITvInputSessionCallback;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputService;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -41,18 +53,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.provider.TvContract;
-import android.tv.ITvInputClient;
-import android.tv.ITvInputHardware;
-import android.tv.ITvInputHardwareCallback;
-import android.tv.ITvInputManager;
-import android.tv.ITvInputService;
-import android.tv.ITvInputServiceCallback;
-import android.tv.ITvInputSession;
-import android.tv.ITvInputSessionCallback;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvInputInfo;
-import android.tv.TvInputService;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.InputChannel;
@@ -63,6 +63,10 @@
 import com.android.server.IoThread;
 import com.android.server.SystemService;
 
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -145,7 +149,8 @@
         if (DEBUG) Slog.d(TAG, "buildTvInputList");
         PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> services = pm.queryIntentServices(
-                new Intent(TvInputService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
+                new Intent(TvInputService.SERVICE_INTERFACE),
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
         for (ResolveInfo ri : services) {
             ServiceInfo si = ri.serviceInfo;
             if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
@@ -153,9 +158,13 @@
                         + android.Manifest.permission.BIND_TV_INPUT);
                 continue;
             }
-            TvInputInfo info = new TvInputInfo(ri);
-            if (DEBUG) Slog.d(TAG, "add " + info.getId());
-            userState.inputMap.put(info.getId(), info);
+            try {
+                TvInputInfo info = TvInputInfo.createTvInputInfo(mContext, ri);
+                if (DEBUG) Slog.d(TAG, "add " + info.getId());
+                userState.inputMap.put(info.getId(), info);
+            } catch (IOException | XmlPullParserException e) {
+                Slog.e(TAG, "Can't load TV input " + si.name, e);
+            }
         }
     }
 
@@ -204,11 +213,13 @@
                         Slog.e(TAG, "error in unregisterCallback", e);
                     }
                 }
-                serviceState.mClients.clear();
+                serviceState.mClientTokens.clear();
                 mContext.unbindService(serviceState.mConnection);
             }
             userState.serviceStateMap.clear();
 
+            userState.clientStateMap.clear();
+
             mUserStates.remove(userId);
         }
     }
@@ -273,7 +284,7 @@
             }
             serviceState.mReconnecting = false;
         }
-        boolean isStateEmpty = serviceState.mClients.isEmpty()
+        boolean isStateEmpty = serviceState.mClientTokens.isEmpty()
                 && serviceState.mSessionTokens.isEmpty();
         if (serviceState.mService == null && !isStateEmpty && userId == mCurrentUserId) {
             // This means that the service is not yet connected but its state indicates that we
@@ -304,10 +315,22 @@
         }
     }
 
+    private ClientState createClientStateLocked(IBinder clientToken, int userId) {
+        UserState userState = getUserStateLocked(userId);
+        ClientState clientState = new ClientState(clientToken, userId);
+        try {
+            clientToken.linkToDeath(clientState, 0);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Client is already died.");
+        }
+        userState.clientStateMap.put(clientToken, clientState);
+        return clientState;
+    }
+
     private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken,
             final int userId) {
-        final SessionState sessionState =
-                getUserStateLocked(userId).sessionStateMap.get(sessionToken);
+        final UserState userState = getUserStateLocked(userId);
+        final SessionState sessionState = userState.sessionStateMap.get(sessionToken);
         if (DEBUG) {
             Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInputId + ")");
         }
@@ -333,6 +356,14 @@
                         } catch (RemoteException e) {
                             Slog.e(TAG, "Session is already died.");
                         }
+
+                        IBinder clientToken = sessionState.mClient.asBinder();
+                        ClientState clientState = userState.clientStateMap.get(clientToken);
+                        if (clientState == null) {
+                            clientState = createClientStateLocked(clientToken, userId);
+                        }
+                        clientState.mSessionTokens.add(sessionState.mSessionToken);
+
                         sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId,
                                 sessionToken, channels[0], sessionState.mSeq, userId);
                     }
@@ -423,7 +454,16 @@
             mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget();
         }
 
-        // Also remove the session token from the session token list of the current service.
+        // Also remove the session token from the session token list of the current client and
+        // service.
+        ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder());
+        if (clientState != null) {
+            clientState.mSessionTokens.remove(sessionToken);
+            if (clientState.isEmpty()) {
+                userState.clientStateMap.remove(sessionState.mClient.asBinder());
+            }
+        }
+
         ServiceState serviceState = userState.serviceStateMap.get(sessionState.mInputId);
         if (serviceState != null) {
             serviceState.mSessionTokens.remove(sessionToken);
@@ -431,11 +471,45 @@
         updateServiceConnectionLocked(sessionState.mInputId, userId);
     }
 
+    private void unregisterCallbackInternalLocked(IBinder clientToken, String inputId,
+            int userId) {
+        UserState userState = getUserStateLocked(userId);
+        ClientState clientState = userState.clientStateMap.get(clientToken);
+        if (clientState != null) {
+            clientState.mInputIds.remove(inputId);
+            if (clientState.isEmpty()) {
+                userState.clientStateMap.remove(clientToken);
+            }
+        }
+
+        ServiceState serviceState = userState.serviceStateMap.get(inputId);
+        if (serviceState == null) {
+            return;
+        }
+
+        // Remove this client from the client list and unregister the callback.
+        serviceState.mClientTokens.remove(clientToken);
+        if (!serviceState.mClientTokens.isEmpty()) {
+            // We have other clients who want to keep the callback. Do this later.
+            return;
+        }
+        if (serviceState.mService == null || serviceState.mCallback == null) {
+            return;
+        }
+        try {
+            serviceState.mService.unregisterCallback(serviceState.mCallback);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "error in unregisterCallback", e);
+        } finally {
+            serviceState.mCallback = null;
+            updateServiceConnectionLocked(inputId, userId);
+        }
+    }
+
     private void broadcastServiceAvailabilityChangedLocked(ServiceState serviceState) {
-        for (IBinder iBinder : serviceState.mClients) {
-            ITvInputClient client = ITvInputClient.Stub.asInterface(iBinder);
+        for (IBinder clientToken : serviceState.mClientTokens) {
             try {
-                client.onAvailabilityChanged(
+                ITvInputClient.Stub.asInterface(clientToken).onAvailabilityChanged(
                         serviceState.mTvInputInfo.getId(), serviceState.mAvailable);
             } catch (RemoteException e) {
                 Slog.e(TAG, "error in onAvailabilityChanged", e);
@@ -498,10 +572,19 @@
                                 userState.inputMap.get(inputId), resolvedUserId);
                         userState.serviceStateMap.put(inputId, serviceState);
                     }
-                    IBinder iBinder = client.asBinder();
-                    if (!serviceState.mClients.contains(iBinder)) {
-                        serviceState.mClients.add(iBinder);
+                    IBinder clientToken = client.asBinder();
+                    if (!serviceState.mClientTokens.contains(clientToken)) {
+                        serviceState.mClientTokens.add(clientToken);
                     }
+
+                    ClientState clientState = userState.clientStateMap.get(clientToken);
+                    if (clientState == null) {
+                        clientState = createClientStateLocked(clientToken, resolvedUserId);
+                    }
+                    if (!clientState.mInputIds.contains(inputId)) {
+                        clientState.mInputIds.add(inputId);
+                    }
+
                     if (serviceState.mService != null) {
                         if (serviceState.mCallback != null) {
                             // We already handled.
@@ -529,29 +612,7 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
-                    UserState userState = getUserStateLocked(resolvedUserId);
-                    ServiceState serviceState = userState.serviceStateMap.get(inputId);
-                    if (serviceState == null) {
-                        return;
-                    }
-
-                    // Remove this client from the client list and unregister the callback.
-                    serviceState.mClients.remove(client.asBinder());
-                    if (!serviceState.mClients.isEmpty()) {
-                        // We have other clients who want to keep the callback. Do this later.
-                        return;
-                    }
-                    if (serviceState.mService == null || serviceState.mCallback == null) {
-                        return;
-                    }
-                    try {
-                        serviceState.mService.unregisterCallback(serviceState.mCallback);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in unregisterCallback", e);
-                    } finally {
-                        serviceState.mCallback = null;
-                        updateServiceConnectionLocked(inputId, resolvedUserId);
-                    }
+                    unregisterCallbackInternalLocked(client.asBinder(), inputId, resolvedUserId);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -582,8 +643,8 @@
 
                     // Create a new session token and a session state.
                     IBinder sessionToken = new Binder();
-                    SessionState sessionState = new SessionState(
-                            sessionToken, inputId, client, seq, callingUid, resolvedUserId);
+                    SessionState sessionState = new SessionState(sessionToken, inputId, client,
+                            seq, callingUid, resolvedUserId);
 
                     // Add them to the global session state map of the current user.
                     userState.sessionStateMap.put(sessionToken, sessionState);
@@ -835,6 +896,10 @@
         // A mapping from the TV input id to its TvInputInfo.
         private final Map<String, TvInputInfo> inputMap = new HashMap<String,TvInputInfo>();
 
+        // A mapping from the token of a client to its state.
+        private final Map<IBinder, ClientState> clientStateMap =
+                new HashMap<IBinder, ClientState>();
+
         // A mapping from the name of a TV input service to its state.
         private final Map<String, ServiceState> serviceStateMap =
                 new HashMap<String, ServiceState>();
@@ -844,9 +909,46 @@
                 new HashMap<IBinder, SessionState>();
     }
 
+    private final class ClientState implements IBinder.DeathRecipient {
+        private final List<String> mInputIds = new ArrayList<String>();
+        private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
+
+        private IBinder mClientToken;
+        private final int mUserId;
+
+        ClientState(IBinder clientToken, int userId) {
+            mClientToken = clientToken;
+            mUserId = userId;
+        }
+
+        public boolean isEmpty() {
+            return mInputIds.isEmpty() && mSessionTokens.isEmpty();
+        }
+
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                UserState userState = getUserStateLocked(mUserId);
+                // DO NOT remove the client state of clientStateMap in this method. It will be
+                // removed in releaseSessionLocked() or unregisterCallbackInternalLocked().
+                ClientState clientState = userState.clientStateMap.get(mClientToken);
+                if (clientState != null) {
+                    while (clientState.mSessionTokens.size() > 0) {
+                        releaseSessionLocked(
+                                clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId);
+                    }
+                    while (clientState.mInputIds.size() > 0) {
+                        unregisterCallbackInternalLocked(
+                                mClientToken, clientState.mInputIds.get(0), mUserId);
+                    }
+                }
+                mClientToken = null;
+            }
+        }
+    }
+
     private final class ServiceState {
-        // TODO: need to implement DeathRecipient for clients.
-        private final List<IBinder> mClients = new ArrayList<IBinder>();
+        private final List<IBinder> mClientTokens = new ArrayList<IBinder>();
         private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
         private final ServiceConnection mConnection;
         private final TvInputInfo mTvInputInfo;
@@ -869,13 +971,13 @@
         private final int mSeq;
         private final int mCallingUid;
         private final int mUserId;
-        private final IBinder mToken;
+        private final IBinder mSessionToken;
         private ITvInputSession mSession;
         private Uri mLogUri;
 
-        private SessionState(IBinder token, String inputId, ITvInputClient client, int seq,
+        private SessionState(IBinder sessionToken, String inputId, ITvInputClient client, int seq,
                 int callingUid, int userId) {
-            mToken = token;
+            mSessionToken = sessionToken;
             mInputId = inputId;
             mClient = client;
             mSeq = seq;
@@ -894,7 +996,7 @@
                         Slog.e(TAG, "error in onSessionReleased", e);
                     }
                 }
-                removeSessionStateLocked(mToken, mUserId);
+                removeSessionStateLocked(mSessionToken, mUserId);
             }
         }
     }
@@ -918,7 +1020,7 @@
                 serviceState.mService = ITvInputService.Stub.asInterface(service);
 
                 // Register a callback, if we need to.
-                if (!serviceState.mClients.isEmpty() && serviceState.mCallback == null) {
+                if (!serviceState.mClientTokens.isEmpty() && serviceState.mCallback == null) {
                     serviceState.mCallback = new ServiceCallback(mUserId);
                     try {
                         serviceState.mService.registerCallback(serviceState.mCallback);
@@ -1046,7 +1148,7 @@
                     TvContract.Programs.COLUMN_TITLE,
                     TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
                     TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS,
-                    TvContract.Programs.COLUMN_DESCRIPTION
+                    TvContract.Programs.COLUMN_SHORT_DESCRIPTION
             };
             String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND "
                     + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND "
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index 35d19c1..29bab22 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -21,6 +21,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.view.Display;
 import android.view.Surface;
@@ -32,6 +33,10 @@
     private static final String TAG = "CircularDisplayMask";
 
     private static final int STROKE_WIDTH = 2;
+    // half the screen size
+    private static final int CIRCLE_RADIUS = 160;
+    // size of the chin
+    private static final int SCREEN_OFFSET = 30;
 
     private final SurfaceControl mSurfaceControl;
     private final Surface mSurface = new Surface();
@@ -40,12 +45,13 @@
     private boolean mDrawNeeded;
     private Paint mPaint;
     private int mRotation;
+    private boolean mVisible;
 
     public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) {
         SurfaceControl ctrl = null;
         try {
             ctrl = new SurfaceControl(session, "CircularDisplayMask",
-                320, 290, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+                320, 320, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
             ctrl.setLayerStack(display.getLayerStack());
             ctrl.setLayer(zOrder);
             ctrl.setPosition(0, 0);
@@ -63,12 +69,12 @@
     }
 
     private void drawIfNeeded() {
-        if (!mDrawNeeded) {
+        if (!mDrawNeeded || !mVisible) {
             return;
         }
         mDrawNeeded = false;
 
-        Rect dirty = new Rect(0, 0, mLastDW, mLastDH);
+        Rect dirty = new Rect(0, 0, 320, 320);
         Canvas c = null;
         try {
             c = mSurface.lockCanvas(dirty);
@@ -78,27 +84,23 @@
         if (c == null) {
             return;
         }
-        int cx = 160;
-        int cy = 160;
+        c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
         switch (mRotation) {
-            case Surface.ROTATION_0:
-            case Surface.ROTATION_90:
-                // chin bottom or right
-                cx = 160;
-                cy = 160;
-                break;
-            case Surface.ROTATION_180:
-                // chin top
-                cx = 160;
-                cy = 145;
-                break;
-            case Surface.ROTATION_270:
-                cx = 145;
-                cy = 160;
-                break;
+        case Surface.ROTATION_0:
+        case Surface.ROTATION_90:
+            // chin bottom or right
+            mSurfaceControl.setPosition(0, 0);
+            break;
+        case Surface.ROTATION_180:
+            // chin top
+            mSurfaceControl.setPosition(0, -SCREEN_OFFSET);
+            break;
+        case Surface.ROTATION_270:
+            // chin left
+            mSurfaceControl.setPosition(-SCREEN_OFFSET, 0);
+            break;
         }
-        c.drawCircle(cx, cy, 160, mPaint);
-
+        c.drawCircle(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS, mPaint);
         mSurface.unlockCanvasAndPost(c);
     }
 
@@ -108,6 +110,7 @@
         if (mSurfaceControl == null) {
             return;
         }
+        mVisible = on;
         drawIfNeeded();
         if (on) {
             mSurfaceControl.show();
@@ -117,14 +120,14 @@
     }
 
     void positionSurface(int dw, int dh, int rotation) {
-        if (mLastDW == dw && mLastDH == dh) {
+        if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
             return;
         }
         mLastDW = dw;
         mLastDH = dh;
-        mSurfaceControl.setSize(dw, dh);
         mDrawNeeded = true;
         mRotation = rotation;
+        drawIfNeeded();
     }
 
 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 81db8b3..a354c45 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -174,14 +174,14 @@
             stackNdx = 0;
         } else {
             stackNdx = mTasks.size();
-            final int currentUserId = mService.mCurrentUserId;
-            if (task.mUserId != currentUserId) {
+            if (!mService.isCurrentProfileLocked(task.mUserId)) {
                 // Place the task below all current user tasks.
                 while (--stackNdx >= 0) {
-                    if (currentUserId != mTasks.get(stackNdx).mUserId) {
+                    if (!mService.isCurrentProfileLocked(mTasks.get(stackNdx).mUserId)) {
                         break;
                     }
                 }
+                // Put it above first non-current user task.
                 ++stackNdx;
             }
         }
@@ -352,7 +352,7 @@
         int top = mTasks.size();
         for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
             Task task = mTasks.get(taskNdx);
-            if (task.mUserId == userId) {
+            if (mService.isCurrentProfileLocked(task.mUserId)) {
                 mTasks.remove(taskNdx);
                 mTasks.add(task);
                 --top;
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index 6c14887..c2fccc1 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -139,6 +139,8 @@
  * the HW module and obtaining the proper interfaces.
  */
 static void ClassInit(JNIEnv* env, jclass clazz) {
+  sFlpInterface = NULL;
+
   // get references to the Java provider methods
   sOnLocationReport = env->GetMethodID(
       clazz,
@@ -163,6 +165,38 @@
   sOnGeofenceRemove = env->GetMethodID(clazz, "onGeofenceRemove", "(II)V");
   sOnGeofencePause = env->GetMethodID(clazz, "onGeofencePause", "(II)V");
   sOnGeofenceResume = env->GetMethodID(clazz, "onGeofenceResume", "(II)V");
+
+  // open the hardware module
+  const hw_module_t* module = NULL;
+  int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
+  if (err != 0) {
+    ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
+    return;
+  }
+
+  err = module->methods->open(
+      module,
+      FUSED_LOCATION_HARDWARE_MODULE_ID,
+      &sHardwareDevice);
+  if (err != 0) {
+    ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
+    return;
+  }
+
+  // acquire the interfaces pointers
+  flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
+  sFlpInterface = flp_device->get_flp_interface(flp_device);
+
+  if (sFlpInterface != NULL) {
+    sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
+        sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE));
+
+    sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
+        sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE));
+
+    sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
+        sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE));
+  }
 }
 
 /*
@@ -637,44 +671,6 @@
  * the Flp interfaces are initialized properly.
  */
 static void Init(JNIEnv* env, jobject obj) {
-  if(sHardwareDevice != NULL) {
-    ALOGD("Hardware Device already opened.");
-    return;
-  }
-
-  const hw_module_t* module = NULL;
-  int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
-  if(err != 0) {
-    ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
-    return;
-  }
-
-  err = module->methods->open(
-        module,
-        FUSED_LOCATION_HARDWARE_MODULE_ID, &sHardwareDevice);
-  if(err != 0) {
-    ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
-    return;
-  }
-
-  sFlpInterface = NULL;
-  flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
-  sFlpInterface = flp_device->get_flp_interface(flp_device);
-
-  if(sFlpInterface != NULL) {
-    sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
-        sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE)
-        );
-
-    sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
-        sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE)
-        );
-
-    sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
-        sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE)
-        );
-  }
-
   if(sCallbacksObj == NULL) {
     sCallbacksObj = env->NewGlobalRef(obj);
   }
@@ -696,7 +692,10 @@
 }
 
 static jboolean IsSupported(JNIEnv* env, jclass clazz) {
-  return sFlpInterface != NULL;
+  if (sFlpInterface == NULL) {
+    return JNI_FALSE;
+  }
+  return JNI_TRUE;
 }
 
 static jint GetBatchSize(JNIEnv* env, jobject object) {
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index f0c4f3a..afe629d 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -316,7 +316,7 @@
             (void*) nativeOpen },
     { "nativeSetSurface", "(JIILandroid/view/Surface;)I",
             (void*) nativeSetSurface },
-    { "nativeGetStreamConfigs", "(JII)[Landroid/tv/TvStreamConfig;",
+    { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;",
             (void*) nativeGetStreamConfigs },
     { "nativeClose", "(J)V",
             (void*) nativeClose },
@@ -346,10 +346,10 @@
             gTvInputHalClassInfo.streamConfigsChanged, clazz,
             "streamConfigsChangedFromNative", "(I)V");
 
-    FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/tv/TvStreamConfig");
+    FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig");
     gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz));
 
-    FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/tv/TvStreamConfig$Builder");
+    FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder");
     gTvStreamConfigBuilderClassInfo.clazz =
             jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz));
 
@@ -360,27 +360,27 @@
     GET_METHOD_ID(
             gTvStreamConfigBuilderClassInfo.streamId,
             gTvStreamConfigBuilderClassInfo.clazz,
-            "streamId", "(I)Landroid/tv/TvStreamConfig$Builder;");
+            "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
     GET_METHOD_ID(
             gTvStreamConfigBuilderClassInfo.type,
             gTvStreamConfigBuilderClassInfo.clazz,
-            "type", "(I)Landroid/tv/TvStreamConfig$Builder;");
+            "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
     GET_METHOD_ID(
             gTvStreamConfigBuilderClassInfo.maxWidth,
             gTvStreamConfigBuilderClassInfo.clazz,
-            "maxWidth", "(I)Landroid/tv/TvStreamConfig$Builder;");
+            "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
     GET_METHOD_ID(
             gTvStreamConfigBuilderClassInfo.maxHeight,
             gTvStreamConfigBuilderClassInfo.clazz,
-            "maxHeight", "(I)Landroid/tv/TvStreamConfig$Builder;");
+            "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
     GET_METHOD_ID(
             gTvStreamConfigBuilderClassInfo.generation,
             gTvStreamConfigBuilderClassInfo.clazz,
-            "generation", "(I)Landroid/tv/TvStreamConfig$Builder;");
+            "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
     GET_METHOD_ID(
             gTvStreamConfigBuilderClassInfo.build,
             gTvStreamConfigBuilderClassInfo.clazz,
-            "build", "()Landroid/tv/TvStreamConfig;");
+            "build", "()Landroid/media/tv/TvStreamConfig;");
 
     return 0;
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9174c0c..18ece5b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.media.AudioService;
+import android.media.tv.TvInputManager;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
@@ -43,7 +44,6 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.service.dreams.DreamService;
-import android.tv.TvInputManager;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -127,7 +127,7 @@
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
     private static final String WIFI_PASSPOINT_SERVICE_CLASS =
-            "com.android.server.wifi.passpoint.PasspointService";
+            "com.android.server.wifi.passpoint.WifiPasspointService";
     private static final String WIFI_P2P_SERVICE_CLASS =
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String HDMI_CEC_SERVICE_CLASS =
@@ -644,18 +644,18 @@
                 }
 
                 try {
-                    mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
-                } catch (Throwable e) {
-                    reportWtf("starting Wi-Fi Service", e);
-                }
-
-                try {
                     mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
                 } catch (Throwable e) {
                     reportWtf("starting Wi-Fi PasspointService", e);
                 }
 
                 try {
+                    mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
+                } catch (Throwable e) {
+                    reportWtf("starting Wi-Fi Service", e);
+                }
+
+                try {
                     Slog.i(TAG, "Wi-Fi Scanning Service");
                     mSystemServiceManager.startService(
                             "com.android.server.wifi.WifiScanningService");
diff --git a/telecomm/java/android/telecomm/CallService.java b/telecomm/java/android/telecomm/CallService.java
index 51f10c1..d452172 100644
--- a/telecomm/java/android/telecomm/CallService.java
+++ b/telecomm/java/android/telecomm/CallService.java
@@ -27,6 +27,8 @@
 import com.android.internal.telecomm.ICallService;
 import com.android.internal.telecomm.ICallServiceAdapter;
 
+import java.util.List;
+
 /**
  * Base implementation of CallService which can be used to provide calls for the system
  * in-call UI. CallService is a one-way service from the framework's CallsManager to any app
@@ -59,6 +61,8 @@
     private static final int MSG_ON_AUDIO_STATE_CHANGED = 11;
     private static final int MSG_PLAY_DTMF_TONE = 12;
     private static final int MSG_STOP_DTMF_TONE = 13;
+    private static final int MSG_ADD_TO_CONFERENCE = 14;
+    private static final int MSG_SPLIT_FROM_CONFERENCE = 15;
 
     /**
      * Default Handler used to consolidate binder method calls onto a single thread.
@@ -123,6 +127,29 @@
                 case MSG_STOP_DTMF_TONE:
                     stopDtmfTone((String) msg.obj);
                     break;
+                case MSG_ADD_TO_CONFERENCE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        @SuppressWarnings("unchecked")
+                        List<String> callIds = (List<String>) args.arg2;
+                        String conferenceCallId = (String) args.arg1;
+                        addToConference(conferenceCallId, callIds);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_SPLIT_FROM_CONFERENCE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String conferenceCallId = (String) args.arg1;
+                        String callId = (String) args.arg2;
+                        splitFromConference(conferenceCallId, callId);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -204,6 +231,22 @@
             args.arg2 = audioState;
             mMessageHandler.obtainMessage(MSG_ON_AUDIO_STATE_CHANGED, args).sendToTarget();
         }
+
+        @Override
+        public void addToConference(String conferenceCallId, List<String> callsToConference) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = conferenceCallId;
+            args.arg2 = callsToConference;
+            mMessageHandler.obtainMessage(MSG_ADD_TO_CONFERENCE, args).sendToTarget();
+        }
+
+        @Override
+        public void splitFromConference(String conferenceCallId, String callId) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = conferenceCallId;
+            args.arg2 = callId;
+            mMessageHandler.obtainMessage(MSG_SPLIT_FROM_CONFERENCE, args).sendToTarget();
+        }
     }
 
     /**
@@ -359,4 +402,24 @@
      * @param audioState The new {@link CallAudioState}.
      */
     public abstract void onAudioStateChanged(String activeCallId, CallAudioState audioState);
+
+    /**
+     * Adds the specified calls to the specified conference call.
+     *
+     * @param conferenceCallId The unique ID of the conference call onto which the specified calls
+     *         should be added.
+     * @param callIds The calls to add to the conference call.
+     * @hide
+     */
+    public abstract void addToConference(String conferenceCallId, List<String> callIds);
+
+    /**
+     * Removes the specified call from the specified conference call. This is a no-op if the call
+     * is not already part of the conference call.
+     *
+     * @param conferenceCallId The conference call.
+     * @param callId The call to remove from the conference call
+     * @hide
+     */
+    public abstract void splitFromConference(String conferenceCallId, String callId);
 }
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index dafc310..7396808 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -20,6 +20,8 @@
 
 import com.android.internal.telecomm.ICallServiceAdapter;
 
+import java.util.List;
+
 /**
  * Provides methods for ICallService implementations to interact with the system phone app.
  * TODO(santoscordon): Need final public-facing comments in this file.
@@ -169,4 +171,46 @@
         }
     }
 
+    /**
+     * Indicates that the specified call can conference with any of the specified list of calls.
+     *
+     * @param callId The unique ID of the call.
+     * @param conferenceCapableCallIds The unique IDs of the calls which can be conferenced.
+     * @hide
+     */
+    public void setCanConferenceWith(String callId, List<String> conferenceCapableCallIds) {
+        try {
+            mAdapter.setCanConferenceWith(callId, conferenceCapableCallIds);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Indicates whether or not the specified call is currently conferenced into the specified
+     * conference call.
+     *
+     * @param conferenceCallId The unique ID of the conference call.
+     * @param callId The unique ID of the call being conferenced.
+     * @hide
+     */
+    public void setIsConferenced(String conferenceCallId, String callId, boolean isConferenced) {
+        try {
+            mAdapter.setIsConferenced(conferenceCallId, callId, isConferenced);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Indicates that the call no longer exists. Can be used with either a call or a conference
+     * call.
+     *
+     * @param callId The unique ID of the call.
+     * @hide
+     */
+    public void removeCall(String callId) {
+        try {
+            mAdapter.removeCall(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 8d02842..aeb1c33 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -20,6 +20,8 @@
 import android.os.Bundle;
 
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -248,6 +250,39 @@
         findConnectionForAction(callId, "onAudioStateChanged").setAudioState(audioState);
     }
 
+    /** @hide */
+    @Override
+    public final void addToConference(String conferenceCallId, List<String> callIds) {
+        Log.d(this, "addToConference %s, %s", conferenceCallId, callIds);
+
+        List<Connection> connections = new LinkedList<>();
+        for (String id : callIds) {
+            Connection connection = findConnectionForAction(id, "addToConference");
+            if (connection == NULL_CONNECTION) {
+                Log.w(this, "Connection missing in conference request %s.", id);
+                return;
+            }
+            connections.add(connection);
+        }
+
+        // TODO(santoscordon): Find an existing conference call or create a new one. Then call
+        // conferenceWith on it.
+    }
+
+    /** @hide */
+    @Override
+    public final void splitFromConference(String conferenceCallId, String callId) {
+        Log.d(this, "splitFromConference(%s, %s)", conferenceCallId, callId);
+
+        Connection connection = findConnectionForAction(callId, "splitFromConference");
+        if (connection == NULL_CONNECTION) {
+            Log.w(this, "Connection missing in conference request %s.", callId);
+            return;
+        }
+
+        // TODO(santoscordon): Find existing conference call and invoke split(connection).
+    }
+
     /**
      * Find a set of Subscriptions matching a given handle (e.g. phone number).
      *
@@ -342,4 +377,4 @@
         Log.w(this, "%s - Cannot find Connection %s", action, callId);
         return NULL_CONNECTION;
     }
-}
\ No newline at end of file
+}
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index e41d3f6..6838ede 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -196,4 +196,32 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Instructs Telecomm to conference the specified calls together.
+     *
+     * @param callId The unique ID of the call.
+     * @param callIdToConference The unique ID of the call to conference with.
+     * @hide
+     */
+    void conferenceWith(String callId, String callIdToConference) {
+        try {
+            mAdapter.conferenceWith(callId, callIdToConference);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Instructs Telecomm to split the specified call from any conference call with which it may be
+     * connected.
+     *
+     * @param callId The unique ID of the call.
+     * @hide
+     */
+    void splitFromConference(String callId) {
+        try {
+            mAdapter.splitFromConference(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/InCallCall.java b/telecomm/java/android/telecomm/InCallCall.java
index c3b2ae7..346d2077 100644
--- a/telecomm/java/android/telecomm/InCallCall.java
+++ b/telecomm/java/android/telecomm/InCallCall.java
@@ -17,13 +17,13 @@
 package android.telecomm;
 
 import android.net.Uri;
-import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.DisconnectCause;
 
-import java.util.Date;
-import java.util.UUID;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Information about a call that is used between InCallService and Telecomm.
@@ -38,6 +38,26 @@
     private final GatewayInfo mGatewayInfo;
     private final CallServiceDescriptor mCurrentCallServiceDescriptor;
     private final CallServiceDescriptor mHandoffCallServiceDescriptor;
+    private final List<String> mConferenceCapableCallIds;
+    private final String mParentCallId;
+    private final List<String> mChildCallIds;
+
+    /** @hide */
+    @SuppressWarnings("unchecked")
+    public InCallCall(
+            String id,
+            CallState state,
+            int disconnectCause,
+            int capabilities,
+            long connectTimeMillis,
+            Uri handle,
+            GatewayInfo gatewayInfo,
+            CallServiceDescriptor descriptor,
+            CallServiceDescriptor handoffDescriptor) {
+        this(id, state, disconnectCause, capabilities, connectTimeMillis, handle, gatewayInfo,
+                descriptor, handoffDescriptor, Collections.EMPTY_LIST, null,
+                Collections.EMPTY_LIST);
+    }
 
     /** @hide */
     public InCallCall(
@@ -49,7 +69,10 @@
             Uri handle,
             GatewayInfo gatewayInfo,
             CallServiceDescriptor descriptor,
-            CallServiceDescriptor handoffDescriptor) {
+            CallServiceDescriptor handoffDescriptor,
+            List<String> conferenceCapableCallIds,
+            String parentCallId,
+            List<String> childCallIds) {
         mId = id;
         mState = state;
         mDisconnectCause = disconnectCause;
@@ -59,6 +82,9 @@
         mGatewayInfo = gatewayInfo;
         mCurrentCallServiceDescriptor = descriptor;
         mHandoffCallServiceDescriptor = handoffDescriptor;
+        mConferenceCapableCallIds = conferenceCapableCallIds;
+        mParentCallId = parentCallId;
+        mChildCallIds = childCallIds;
     }
 
     /** The unique ID of the call. */
@@ -112,6 +138,31 @@
         return mHandoffCallServiceDescriptor;
     }
 
+    /**
+     * The calls with which this call can conference.
+     * @hide
+     */
+    public List<String> getConferenceCapableCallIds() {
+        return mConferenceCapableCallIds;
+    }
+
+    /**
+     * The conference call to which this call is conferenced. Null if not conferenced.
+     * @hide
+     */
+    public String getParentCallId() {
+        return mParentCallId;
+    }
+
+    /**
+     * The child call-IDs if this call is a conference call. Returns an empty list if this is not
+     * a conference call or if the conference call contains no children.
+     * @hide
+     */
+    public List<String> getChildCallIds() {
+        return mChildCallIds;
+    }
+
     /** Responsible for creating InCallCall objects for deserialized Parcels. */
     public static final Parcelable.Creator<InCallCall> CREATOR =
             new Parcelable.Creator<InCallCall> () {
@@ -127,8 +178,14 @@
             GatewayInfo gatewayInfo = source.readParcelable(classLoader);
             CallServiceDescriptor descriptor = source.readParcelable(classLoader);
             CallServiceDescriptor handoffDescriptor = source.readParcelable(classLoader);
+            List<String> conferenceCapableCallIds = new ArrayList<>();
+            source.readList(conferenceCapableCallIds, classLoader);
+            String parentCallId = source.readString();
+            List<String> childCallIds = new ArrayList<>();
+            source.readList(childCallIds, classLoader);
             return new InCallCall(id, state, disconnectCause, capabilities, connectTimeMillis,
-                    handle, gatewayInfo, descriptor, handoffDescriptor);
+                    handle, gatewayInfo, descriptor, handoffDescriptor, conferenceCapableCallIds,
+                    parentCallId, childCallIds);
         }
 
         @Override
@@ -155,5 +212,8 @@
         destination.writeParcelable(mGatewayInfo, 0);
         destination.writeParcelable(mCurrentCallServiceDescriptor, 0);
         destination.writeParcelable(mHandoffCallServiceDescriptor, 0);
+        destination.writeList(mConferenceCapableCallIds);
+        destination.writeString(mParentCallId);
+        destination.writeList(mChildCallIds);
     }
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ICallService.aidl b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
index cc0641c..771a3ae 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
@@ -55,4 +55,8 @@
     void playDtmfTone(String callId, char digit);
 
     void stopDtmfTone(String callId);
+
+    void addToConference(String conferenceCallId, in List<String> callIds);
+
+    void splitFromConference(String conferenceCallId, String callId);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index 6d36494..a92b176 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -45,4 +45,10 @@
     void setOnHold(String callId);
 
     void setRequestingRingback(String callId, boolean ringing);
+
+    void setCanConferenceWith(String callId, in List<String> conferenceCapableCallIds);
+
+    void setIsConferenced(String conferenceCallId, String callId, boolean isConferenced);
+
+    void removeCall(String callId);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 512e898..6a27217 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -47,4 +47,8 @@
     void postDialContinue(String callId);
 
     void handoffCall(String callId);
+
+    void conferenceWith(String callId, String callIdToConference);
+
+    void splitFromConference(String callId);
 }
diff --git a/test-runner/src/android/test/MoreAsserts.java b/test-runner/src/android/test/MoreAsserts.java
index fb0faba..3364895 100644
--- a/test-runner/src/android/test/MoreAsserts.java
+++ b/test-runner/src/android/test/MoreAsserts.java
@@ -128,6 +128,33 @@
     }
 
     /**
+     * @hide Asserts that array {@code actual} is the same size and every element equals
+     * those in array {@code expected}. On failure, message indicates first
+     * specific element mismatch.
+     */
+    public static void assertEquals(
+            String message, long[] expected, long[] actual) {
+        if (expected.length != actual.length) {
+            failWrongLength(message, expected.length, actual.length);
+        }
+        for (int i = 0; i < expected.length; i++) {
+            if (expected[i] != actual[i]) {
+                failWrongElement(message, i, expected[i], actual[i]);
+            }
+        }
+    }
+
+    /**
+     * @hide Asserts that array {@code actual} is the same size and every element equals
+     * those in array {@code expected}. On failure, message indicates first
+     * specific element mismatch.
+     */
+    public static void assertEquals(long[] expected, long[] actual) {
+        assertEquals(null, expected, actual);
+    }
+
+
+    /**
      * Asserts that array {@code actual} is the same size and every element equals
      * those in array {@code expected}. On failure, message indicates first
      * specific element mismatch.
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
index 5b0aa66..a81e063 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -118,19 +118,25 @@
                     mRadius, mToggle ? 250.0f : 150.0f));
 
             mRunningAnimations.add(new RenderNodeAnimator(
-                    mPaint, RenderNodeAnimator.PAINT_ALPHA,
-                    mToggle ? 64.0f : 255.0f));
-
-            mRunningAnimations.add(new RenderNodeAnimator(
                     mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
                     mToggle ? 5.0f : 60.0f));
 
-            TimeInterpolator interp = new OvershootInterpolator(3.0f);
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mPaint, RenderNodeAnimator.PAINT_ALPHA, 64.0f));
+
+            // Will be "chained" to run after the above
+            mRunningAnimations.add(new RenderNodeAnimator(
+                    mPaint, RenderNodeAnimator.PAINT_ALPHA, 255.0f));
+
             for (int i = 0; i < mRunningAnimations.size(); i++) {
                 RenderNodeAnimator anim = mRunningAnimations.get(i);
-                anim.setInterpolator(interp);
                 anim.setDuration(1000);
                 anim.setTarget(this);
+                if (i == (mRunningAnimations.size() - 1)) {
+                    // "chain" test
+                    anim.setStartValue(64.0f);
+                    anim.setStartDelay(anim.getDuration());
+                }
                 anim.start();
             }
 
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index c1fa74f..d6f8118 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -82,7 +82,7 @@
         Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
         mSession = man.createSession("OneMedia");
         mSession.addCallback(mCallback);
-        mSession.addTransportControlsCallback(new TransportListener());
+        mSession.addTransportControlsCallback(new TransportCallback());
         mSession.setPlaybackState(mPlaybackState);
         mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
         mSession.setRouteOptions(mRouteOptions);
@@ -255,7 +255,7 @@
         }
     }
 
-    private class TransportListener extends MediaSession.TransportControlsCallback {
+    private class TransportCallback extends MediaSession.TransportControlsCallback {
         @Override
         public void onPlay() {
             mRenderer.onPlay();
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index c7715ad..fc5426c 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -43,7 +43,6 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        HardwareRenderer.sUseRenderThread = true;
         setContentView(R.layout.activity_main);
         ListView lv = (ListView) findViewById(android.R.id.list);
         lv.setDrawSelectorOnTop(true);
diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
index 28c5f33..113dce3 100644
--- a/tests/VectorDrawableTest/AndroidManifest.xml
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -22,6 +22,25 @@
     <application
         android:hardwareAccelerated="true"
         android:label="vector" >
+
+         <activity
+            android:name="VectorDrawablePerformance"
+            android:label="Vector Performance" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="com.android.test.dynamic.TEST" />
+            </intent-filter>
+
+        </activity>
+        <activity
+            android:name="VectorDrawableAnimation"
+            android:label="VectorTestAnimation" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.dynamic.TEST" />
+            </intent-filter>
+        </activity>
         <activity
             android:name="VectorDrawableTest"
             android:label="Vector Icon" >
@@ -41,19 +60,7 @@
                 <category android:name="com.android.test.dynamic.TEST" />
             </intent-filter>
         </activity>
-
-         <activity
-            android:name="VectorDrawablePerformance"
-            android:label="Vector Performance" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="com.android.test.dynamic.TEST" />
-            </intent-filter>
-
-        </activity>
-
-         <activity
+        <activity
             android:name="VectorDrawableDupPerf"
             android:label="Vector Performance of clones" >
             <intent-filter>
diff --git a/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml b/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml
new file mode 100644
index 0000000..a588960
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml
@@ -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.
+-->
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+     android:id="@+id/animation_drawable_vector" android:oneshot="false">
+    <item android:drawable="@drawable/vector_drawable01" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable02" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable03" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable04" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable05" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable06" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable07" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable08" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable09" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable10" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable11" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable12" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable13" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable14" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable15" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable16" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable17" android:duration="300" />
+    <item android:drawable="@drawable/vector_drawable18" android:duration="300" />
+ </animation-list>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
index 850de28..ab5f7f4 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
@@ -25,10 +25,12 @@
     <group>
         <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
               android:name="path2451"
+              android:fill="#00000000"
               android:stroke="#FF000000"
               android:strokeWidth="30.65500000000000"/>
         <path android:pathData="M 365.015 311.066"
               android:name="path2453"
+              android:fill="#00000000"
               android:stroke="#FF000000"
               android:strokeWidth="30.655000000000001"/>
         <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
@@ -38,10 +40,12 @@
               android:strokeWidth="30.655000000000001"/>
         <path android:pathData="M 170.515 451.566L 305.61 313.46"
               android:name="path2457"
+              android:fill="#00000000"
               android:stroke="#000000"
               android:strokeWidth="30.655000000000001"/>
         <path android:pathData="M 557.968 449.974L 426.515 315.375"
               android:name="path2459"
+              android:fill="#00000000"
               android:stroke="#000000"
               android:strokeWidth="30.655000000000001"/>
     </group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
index d0edd8c..3042f6a 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
@@ -27,6 +27,7 @@
         <path
             android:name="pie1"
             android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+            android:fill="#00000000"
             android:stroke="#FF00FF00"
             android:strokeWidth="70"
             android:trimPathEnd=".75"
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
index 1abe1e1..8d4ca61 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
@@ -34,6 +34,7 @@
            a25,25 -30 0,1 100,-50 l 50,-25
            a25,37 -30 0,1 100,-50 l 50,-25
            a25,50 -30 0,1 100,-50 l 50,-25"
+            android:fill="#00000000"
             android:stroke="#FF00FF00"
             android:strokeWidth="10" />
     </group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
index 8e98d02..c28aff4 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
@@ -25,6 +25,7 @@
         <path
                 android:name="house"
                 android:pathData="M200,300 Q400,50 600,300 T1000,300"
+                android:fill="#00000000"
                 android:stroke="#FFFF0000"
                 android:strokeWidth="10"/>
     </group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
index 6d74ebd..d7042fd 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
@@ -27,6 +27,7 @@
         <path
             android:name="house"
             android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:fill="#00000000"
             android:stroke="#FFFFFF00"
             android:strokeWidth="10" />
     </group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
index a890fd6..47a9574 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
@@ -29,6 +29,7 @@
             android:pathData="M10,300 Q400,550 600,300 T1000,300"
             android:pivotX="90"
             android:pivotY="100"
+            android:fill="#00000000"
             android:stroke="#FFFF0000"
             android:strokeWidth="60" />
     </group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml
new file mode 100644
index 0000000..8d38cb5
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml
@@ -0,0 +1,72 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="400" />
+
+    <group android:name="backgroundGroup" >
+        <path
+            android:name="background1"
+            android:fill="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fill="#80000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    </group>
+    <group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 0,0 v 100 M 0,0 h 100"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="20" />
+
+        <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0" >
+            <path
+                android:name="twoLines1"
+                android:pathData="M 0,0 v 100 M 0,0 h 100"
+                android:stroke="#FF00FF00"
+                android:strokeWidth="20" />
+
+            <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0" >
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines2"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml
new file mode 100644
index 0000000..52acd7a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml
@@ -0,0 +1,86 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="400" />
+
+    <group android:name="backgroundGroup" >
+        <path
+            android:name="background1"
+            android:fill="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fill="#80000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    </group>
+    <group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+        <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="20" />
+
+        <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0" >
+            <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:stroke="#FF00FF00"
+                android:strokeWidth="20" />
+
+            <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0" >
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+
+            <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0" >
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fill="?android:attr/colorForeground"
+                        android:stroke="?android:attr/colorForeground"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml
new file mode 100644
index 0000000..c062d70
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml
@@ -0,0 +1,91 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <size
+        android:height="64dp"
+        android:width="64dp" />
+
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="400" />
+
+    <group android:name="backgroundGroup"
+        android:alpha = "0.5" >
+        <path
+            android:name="background1"
+            android:fill="#FF000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fill="#FF000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    </group>
+    <group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0"
+        android:alpha = "0.5" >
+        <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="20" />
+
+        <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0"
+            android:alpha = "0.5" >
+            <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:stroke="#FF00FF00"
+                android:strokeWidth="20" />
+
+            <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0"
+                android:alpha = "0.5">
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:stroke="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+
+            <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0"
+                android:alpha = "0.5">
+                <group android:name="scaleGroup" >
+                    <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fill="?android:attr/colorForeground"
+                        android:stroke="?android:attr/colorForeground"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test01.xml b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
index a9091ab..fc2a15c 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_test01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
@@ -28,7 +28,8 @@
             android:name="002b"
             android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
             android:stroke="#FF0000FF"
-            android:strokeWidth="4" />
+            android:strokeWidth="4"
+            android:fill="#00000000" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test02.xml b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
index ab58c06..9f4abbf 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_test02.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
@@ -28,7 +28,8 @@
             android:name="002b"
             android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
             android:stroke="#FF0000FF"
-            android:strokeWidth="4" />
+            android:strokeWidth="4"
+            android:fill="#00000000" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/values/strings.xml b/tests/VectorDrawableTest/res/values/strings.xml
index 64163c2..b49a1aa 100644
--- a/tests/VectorDrawableTest/res/values/strings.xml
+++ b/tests/VectorDrawableTest/res/values/strings.xml
@@ -15,4 +15,5 @@
 -->
 
 <resources>
+    <string name="twoLinePathData" >"M 0,0 v 100 M 0,0 h 100"</string>
 </resources>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
index 7ba01b1..a23d819 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -61,6 +61,8 @@
             button.setWidth(200);
             button.setBackgroundResource(icon[i]);
             container.addView(button);
+            VectorDrawable vd = (VectorDrawable) button.getBackground();
+            vd.setAlpha((i + 1) * (0xFF / (icon.length + 1)));
         }
 
         setContentView(container);
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java
new file mode 100644
index 0000000..99de037
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java
@@ -0,0 +1,45 @@
+/*
+ * 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.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.AnimationDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+public class VectorDrawableAnimation extends Activity {
+    private static final String LOGCAT = "VectorDrawableAnimation";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Button button = new Button(this);
+        button.setBackgroundResource(R.drawable.animation_drawable_vector);
+
+        button.setOnClickListener(new View.OnClickListener() {
+                @Override
+            public void onClick(View v) {
+                AnimationDrawable frameAnimation = (AnimationDrawable) v.getBackground();
+                // Start the animation (looped playback by default).
+                frameAnimation.start();
+            }
+        });
+
+        setContentView(button);
+    }
+
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index e0624e5..814deb8 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -17,11 +17,11 @@
 import android.content.res.Resources;
 import android.graphics.drawable.VectorDrawable;
 import android.os.Bundle;
-import android.view.View;
 import android.widget.TextView;
 import android.widget.Button;
 import android.widget.GridLayout;
 import android.widget.ScrollView;
+
 import java.text.DecimalFormat;
 
 @SuppressWarnings({"UnusedDeclaration"})
@@ -48,7 +48,10 @@
             R.drawable.vector_drawable18,
             R.drawable.vector_drawable19,
             R.drawable.vector_drawable20,
-            R.drawable.vector_drawable21
+            R.drawable.vector_drawable21,
+            R.drawable.vector_drawable22,
+            R.drawable.vector_drawable23,
+            R.drawable.vector_drawable24,
     };
 
     @Override
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 5a60014..322d86c 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -105,20 +105,12 @@
         "            en\n"
         "            port,en\n"
         "            port,land,en_US\n"
-        "       If you put the special locale, zz_ZZ on the list, it will perform\n"
-        "       pseudolocalization on the default locale, modifying all of the\n"
-        "       strings so you can look for strings that missed the\n"
-        "       internationalization process.  For example:\n"
-        "            port,land,zz_ZZ\n"
         "   -d  one or more device assets to include, separated by commas\n"
         "   -f  force overwrite of existing files\n"
         "   -g  specify a pixel tolerance to force images to grayscale, default 0\n"
         "   -j  specify a jar or zip file containing classes to include\n"
         "   -k  junk path of file(s) added\n"
         "   -m  make package directories under location specified by -J\n"
-#if 0
-        "   -p  pseudolocalize the default configuration\n"
-#endif
         "   -u  update existing packages (add new, replace older, remove deleted files)\n"
         "   -v  verbose output\n"
         "   -x  create extending (non-application) resource IDs\n"
@@ -141,6 +133,8 @@
         "       manifest, making the application debuggable even on production devices.\n"
         "   --include-meta-data\n"
         "       when used with \"dump badging\" also includes meta-data tags.\n"
+        "   --pseudo-localize\n"
+        "       generate resources for pseudo-locales (en-XA and ar-XB).\n"
         "   --min-sdk-version\n"
         "       inserts android:minSdkVersion in to manifest.  If the version is 7 or\n"
         "       higher, the default encoding for resources will be in UTF-8.\n"
@@ -647,6 +641,8 @@
                         goto bail;
                     }
                     gUserIgnoreAssets = argv[0];
+                } else if (strcmp(cp, "-pseudo-localize") == 0) {
+                    bundle.setPseudolocalize(PSEUDO_ACCENTED | PSEUDO_BIDI);
                 } else {
                     fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
                     wantUsage = true;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index f6d7f55..99151c3 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -144,8 +144,7 @@
             distanceCm = source.distanceCm;
             distanceSdCm = source.distanceSdCm;
             seen = source.seen;
-            if (source.passpoint != null)
-                passpoint = new WifiPasspointInfo(source.passpoint);
+            passpoint = source.passpoint;
         }
     }
 
@@ -179,8 +178,7 @@
         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
                 append("(cm)");
 
-        if (passpoint != null)
-            sb.append(", passpoint: [").append(passpoint.toString()).append("]");
+        sb.append(", passpoint: ").append(passpoint != null ? "yes" : "no");
 
         return sb.toString();
     }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 0faaeba..5dfc318 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -495,6 +495,12 @@
     public boolean didSelfAdd;
 
     /**
+     * peer WifiConfiguration this WifiConfiguration was added for
+     * @hide
+     */
+    public String peerWifiConfiguration;
+
+    /**
      * @hide
      * Indicate that a WifiConfiguration is temporary and should not be saved
      * nor considered by AutoJoin.
@@ -980,6 +986,7 @@
             lastConnectUid = source.lastConnectUid;
             lastUpdateUid = source.lastUpdateUid;
             creatorUid = source.creatorUid;
+            peerWifiConfiguration = source.peerWifiConfiguration;
         }
     }
 
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
index 99bea2f..8ab5c1e 100644
--- a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
@@ -88,68 +88,160 @@
                     CONNECTION_CAPABILITY |
                     OSU_PROVIDER;
 
-    /** TODO doc */
-    public String bssid;
 
-    /** TODO doc */
-    public String venueName;
+    public static class WanMetrics {
+        public static final int STATUS_RESERVED = 0;
+        public static final int STATUS_UP = 1;
+        public static final int STATUS_DOWN = 2;
+        public static final int STATUS_TEST = 3;
 
-    /** TODO doc */
-    public String networkAuthType;
+        public int wanInfo;
+        public long downlinkSpeed;
+        public long uplinkSpeed;
+        public int downlinkLoad;
+        public int uplinkLoad;
+        public int lmd;
 
-    /** TODO doc */
-    public String roamingConsortium;
+        public int getLinkStatus() {
+            return wanInfo & 0x3;
+        }
 
-    /** TODO doc */
-    public String ipAddrTypeAvaibility;
+        public boolean getSymmetricLink() {
+            return (wanInfo & (1 << 2)) != 0;
+        }
 
-    /** TODO doc */
-    public String naiRealm;
+        public boolean getAtCapacity() {
+            return (wanInfo & (1 << 3)) != 0;
+        }
 
-    /** TODO doc */
-    public String cellularNetwork;
-
-    /** TODO doc */
-    public String domainName;
-
-    /** TODO doc */
-    public String operatorFriendlyName;
-
-    /** TODO doc */
-    public String wanMetrics;
-
-    /** TODO doc */
-    public String connectionCapability;
-
-    /** TODO doc */
-    public List<WifiPasspointOsuProvider> osuProviderList;
-
-    /** default constructor @hide */
-    public WifiPasspointInfo() {
-        //        osuProviderList = new ArrayList<OsuProvider>();
-    }
-
-    /** copy constructor @hide */
-    public WifiPasspointInfo(WifiPasspointInfo source) {
-        // TODO
-        bssid = source.bssid;
-        venueName = source.venueName;
-        networkAuthType = source.networkAuthType;
-        roamingConsortium = source.roamingConsortium;
-        ipAddrTypeAvaibility = source.ipAddrTypeAvaibility;
-        naiRealm = source.naiRealm;
-        cellularNetwork = source.cellularNetwork;
-        domainName = source.domainName;
-        operatorFriendlyName = source.operatorFriendlyName;
-        wanMetrics = source.wanMetrics;
-        connectionCapability = source.connectionCapability;
-        if (source.osuProviderList != null) {
-            osuProviderList = new ArrayList<WifiPasspointOsuProvider>();
-            for (WifiPasspointOsuProvider osu : source.osuProviderList)
-                osuProviderList.add(new WifiPasspointOsuProvider(osu));
+        @Override
+        public String toString() {
+            return wanInfo + "," + downlinkSpeed + "," + uplinkSpeed + "," +
+                    downlinkLoad + "," + uplinkLoad + "," + lmd;
         }
     }
 
+    public static class IpProtoPort {
+        public static final int STATUS_CLOSED = 0;
+        public static final int STATUS_OPEN = 1;
+        public static final int STATUS_UNKNOWN = 2;
+
+        public int proto;
+        public int port;
+        public int status;
+
+        @Override
+        public String toString() {
+            return proto + "," + port + "," + status;
+        }
+    }
+
+    public static class NetworkAuthType {
+        public static final int TYPE_TERMS_AND_CONDITION = 0;
+        public static final int TYPE_ONLINE_ENROLLMENT = 1;
+        public static final int TYPE_HTTP_REDIRECTION = 2;
+        public static final int TYPE_DNS_REDIRECTION = 3;
+
+        public int type;
+        public String redirectUrl;
+
+        @Override
+        public String toString() {
+            return type + "," + redirectUrl;
+        }
+    }
+
+    public static class IpAddressType {
+        public static final int IPV6_NOT_AVAILABLE = 0;
+        public static final int IPV6_AVAILABLE = 1;
+        public static final int IPV6_UNKNOWN = 2;
+
+        public static final int IPV4_NOT_AVAILABLE = 0;
+        public static final int IPV4_PUBLIC = 1;
+        public static final int IPV4_PORT_RESTRICTED = 2;
+        public static final int IPV4_SINGLE_NAT = 3;
+        public static final int IPV4_DOUBLE_NAT = 4;
+        public static final int IPV4_PORT_RESTRICTED_SINGLE_NAT = 5;
+        public static final int IPV4_PORT_RESTRICTED_DOUBLE_NAT = 6;
+        public static final int IPV4_PORT_UNKNOWN = 7;
+
+        private static final int NULL_VALUE = -1;
+
+        public int availability;
+
+        public int getIpv6Availability() {
+            return availability & 0x3;
+        }
+
+        public int getIpv4Availability() {
+            return (availability & 0xFF) >> 2;
+        }
+
+        @Override
+        public String toString() {
+            return getIpv6Availability() + "," + getIpv4Availability();
+        }
+    }
+
+    public static class NaiRealm {
+        public static final int ENCODING_RFC4282 = 0;
+        public static final int ENCODING_UTF8 = 1;
+
+        public int encoding;
+        public String realm;
+
+        @Override
+        public String toString() {
+            return encoding + "," + realm;
+        }
+    }
+
+    public static class CellularNetwork {
+        public String mcc;
+        public String mnc;
+
+        @Override
+        public String toString() {
+            return mcc + "," + mnc;
+        }
+    }
+
+    /** BSSID */
+    public String bssid;
+
+    /** venue name */
+    public String venueName;
+
+    /** list of network authentication types */
+    public List<NetworkAuthType> networkAuthType;
+
+    /** list of roaming consortium OIs */
+    public List<String> roamingConsortium;
+
+    /** IP address availability */
+    public IpAddressType ipAddrTypeAvailability;
+
+    /** NAI realm */
+    public List<NaiRealm> naiRealm;
+
+    /** 3GPP cellular network */
+    public List<CellularNetwork> cellularNetwork;
+
+    /** fully qualified domain name (FQDN) */
+    public List<String> domainName;
+
+    /** HS 2.0 operator friendly name */
+    public String operatorFriendlyName;
+
+    /** HS 2.0 wan metrics */
+    public WanMetrics wanMetrics;
+
+    /** HS 2.0 list of IP proto port */
+    public List<IpProtoPort> connectionCapability;
+
+    /** HS 2.0 list of OSU providers */
+    public List<WifiPasspointOsuProvider> osuProviderList;
+
     /**
      * Convert mask to ANQP subtypes, for supplicant command use.
      *
@@ -193,46 +285,154 @@
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
+
         sb.append("BSSID: ").append(bssid);
+
         if (venueName != null)
-            sb.append(" venueName: ").append(venueName);
-        if (networkAuthType != null)
-            sb.append(" networkAuthType: ").append(networkAuthType);
-        if (roamingConsortium != null)
-            sb.append(" roamingConsortium: ").append(roamingConsortium);
-        if (ipAddrTypeAvaibility != null)
-            sb.append(" ipAddrTypeAvaibility: ").append(ipAddrTypeAvaibility);
-        if (naiRealm != null)
-            sb.append(" naiRealm: ").append(naiRealm);
-        if (cellularNetwork != null)
-            sb.append(" cellularNetwork: ").append(cellularNetwork);
-        if (domainName != null)
-            sb.append(" domainName: ").append(domainName);
+            sb.append(" venueName: ").append(venueName.replace("\n", "\\n"));
+
+        if (networkAuthType != null) {
+            sb.append(" networkAuthType: ");
+            for (NetworkAuthType auth : networkAuthType)
+                sb.append("(").append(auth.toString()).append(")");
+        }
+
+        if (roamingConsortium != null) {
+            sb.append(" roamingConsortium: ");
+            for (String oi : roamingConsortium)
+                sb.append("(").append(oi).append(")");
+        }
+
+        if (ipAddrTypeAvailability != null) {
+            sb.append(" ipAddrTypeAvaibility: ").append("(")
+              .append(ipAddrTypeAvailability.toString()).append(")");
+        }
+
+        if (naiRealm != null) {
+            sb.append(" naiRealm: ");
+            for (NaiRealm realm : naiRealm)
+                sb.append("(").append(realm.toString()).append(")");
+        }
+
+        if (cellularNetwork != null) {
+            sb.append(" cellularNetwork: ");
+            for (CellularNetwork plmn : cellularNetwork)
+                sb.append("(").append(plmn.toString()).append(")");
+        }
+
+        if (domainName != null) {
+            sb.append(" domainName: ");
+            for (String fqdn : domainName)
+                sb.append("(").append(fqdn).append(")");
+        }
+
         if (operatorFriendlyName != null)
-            sb.append(" operatorFriendlyName: ").append(operatorFriendlyName);
+            sb.append(" operatorFriendlyName: ").append("(")
+              .append(operatorFriendlyName).append(")");
+
         if (wanMetrics != null)
-            sb.append(" wanMetrics: ").append(wanMetrics);
-        if (connectionCapability != null)
-            sb.append(" connectionCapability: ").append(connectionCapability);
-        if (osuProviderList != null)
-            sb.append(" osuProviderList: (size=" + osuProviderList.size() + ")");
+            sb.append(" wanMetrics: ").append("(")
+              .append(wanMetrics.toString()).append(")");
+
+        if (connectionCapability != null) {
+            sb.append(" connectionCapability: ");
+            for (IpProtoPort ip : connectionCapability)
+                sb.append("(").append(ip.toString()).append(")");
+        }
+
+        if (osuProviderList != null) {
+            sb.append(" osuProviderList: ");
+            for (WifiPasspointOsuProvider osu : osuProviderList)
+                sb.append("(").append(osu.toString()).append(")");
+        }
+
         return sb.toString();
     }
 
     /** Implement the Parcelable interface {@hide} */
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeValue(bssid);
-        out.writeValue(venueName);
-        out.writeValue(networkAuthType);
-        out.writeValue(roamingConsortium);
-        out.writeValue(ipAddrTypeAvaibility);
-        out.writeValue(naiRealm);
-        out.writeValue(cellularNetwork);
-        out.writeValue(domainName);
-        out.writeValue(operatorFriendlyName);
-        out.writeValue(wanMetrics);
-        out.writeValue(connectionCapability);
+        out.writeString(bssid);
+        out.writeString(venueName);
+
+        if (networkAuthType == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(networkAuthType.size());
+            for (NetworkAuthType auth : networkAuthType) {
+                out.writeInt(auth.type);
+                out.writeString(auth.redirectUrl);
+            }
+        }
+
+        if (roamingConsortium == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(roamingConsortium.size());
+            for (String oi : roamingConsortium)
+                out.writeString(oi);
+        }
+
+        if (ipAddrTypeAvailability == null) {
+            out.writeInt(IpAddressType.NULL_VALUE);
+        } else {
+            out.writeInt(ipAddrTypeAvailability.availability);
+        }
+
+        if (naiRealm == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(naiRealm.size());
+            for (NaiRealm realm : naiRealm) {
+                out.writeInt(realm.encoding);
+                out.writeString(realm.realm);
+            }
+        }
+
+        if (cellularNetwork == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(cellularNetwork.size());
+            for (CellularNetwork plmn : cellularNetwork) {
+                out.writeString(plmn.mcc);
+                out.writeString(plmn.mnc);
+            }
+        }
+
+
+        if (domainName == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(domainName.size());
+            for (String fqdn : domainName)
+                out.writeString(fqdn);
+        }
+
+        out.writeString(operatorFriendlyName);
+
+        if (wanMetrics == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(1);
+            out.writeInt(wanMetrics.wanInfo);
+            out.writeLong(wanMetrics.downlinkSpeed);
+            out.writeLong(wanMetrics.uplinkSpeed);
+            out.writeInt(wanMetrics.downlinkLoad);
+            out.writeInt(wanMetrics.uplinkLoad);
+            out.writeInt(wanMetrics.lmd);
+        }
+
+        if (connectionCapability == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(connectionCapability.size());
+            for (IpProtoPort ip : connectionCapability) {
+                out.writeInt(ip.proto);
+                out.writeInt(ip.port);
+                out.writeInt(ip.status);
+            }
+        }
+
         if (osuProviderList == null) {
             out.writeInt(0);
         } else {
@@ -254,18 +454,90 @@
                 @Override
                 public WifiPasspointInfo createFromParcel(Parcel in) {
                     WifiPasspointInfo p = new WifiPasspointInfo();
-                    p.bssid = (String) in.readValue(String.class.getClassLoader());
-                    p.venueName = (String) in.readValue(String.class.getClassLoader());
-                    p.networkAuthType = (String) in.readValue(String.class.getClassLoader());
-                    p.roamingConsortium = (String) in.readValue(String.class.getClassLoader());
-                    p.ipAddrTypeAvaibility = (String) in.readValue(String.class.getClassLoader());
-                    p.naiRealm = (String) in.readValue(String.class.getClassLoader());
-                    p.cellularNetwork = (String) in.readValue(String.class.getClassLoader());
-                    p.domainName = (String) in.readValue(String.class.getClassLoader());
-                    p.operatorFriendlyName = (String) in.readValue(String.class.getClassLoader());
-                    p.wanMetrics = (String) in.readValue(String.class.getClassLoader());
-                    p.connectionCapability = (String) in.readValue(String.class.getClassLoader());
-                    int n = in.readInt();
+                    int n;
+
+                    p.bssid = in.readString();
+                    p.venueName = in.readString();
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.networkAuthType = new ArrayList<NetworkAuthType>();
+                        for (int i = 0; i < n; i++) {
+                            NetworkAuthType auth = new NetworkAuthType();
+                            auth.type = in.readInt();
+                            auth.redirectUrl = in.readString();
+                            p.networkAuthType.add(auth);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.roamingConsortium = new ArrayList<String>();
+                        for (int i = 0; i < n; i++)
+                            p.roamingConsortium.add(in.readString());
+                    }
+
+                    n = in.readInt();
+                    if (n != IpAddressType.NULL_VALUE) {
+                        p.ipAddrTypeAvailability = new IpAddressType();
+                        p.ipAddrTypeAvailability.availability = n;
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.naiRealm = new ArrayList<NaiRealm>();
+                        for (int i = 0; i < n; i++) {
+                            NaiRealm realm = new NaiRealm();
+                            realm.encoding = in.readInt();
+                            realm.realm = in.readString();
+                            p.naiRealm.add(realm);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.cellularNetwork = new ArrayList<CellularNetwork>();
+                        for (int i = 0; i < n; i++) {
+                            CellularNetwork plmn = new CellularNetwork();
+                            plmn.mcc = in.readString();
+                            plmn.mnc = in.readString();
+                            p.cellularNetwork.add(plmn);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.domainName = new ArrayList<String>();
+                        for (int i = 0; i < n; i++)
+                            p.domainName.add(in.readString());
+                    }
+
+                    p.operatorFriendlyName = in.readString();
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.wanMetrics = new WanMetrics();
+                        p.wanMetrics.wanInfo = in.readInt();
+                        p.wanMetrics.downlinkSpeed = in.readLong();
+                        p.wanMetrics.uplinkSpeed = in.readLong();
+                        p.wanMetrics.downlinkLoad = in.readInt();
+                        p.wanMetrics.uplinkLoad = in.readInt();
+                        p.wanMetrics.lmd = in.readInt();
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.connectionCapability = new ArrayList<IpProtoPort>();
+                        for (int i = 0; i < n; i++) {
+                            IpProtoPort ip = new IpProtoPort();
+                            ip.proto = in.readInt();
+                            ip.port = in.readInt();
+                            ip.status = in.readInt();
+                            p.connectionCapability.add(ip);
+                        }
+                    }
+
+                    n = in.readInt();
                     if (n > 0) {
                         p.osuProviderList = new ArrayList<WifiPasspointOsuProvider>();
                         for (int i = 0; i < n; i++) {
@@ -274,6 +546,7 @@
                             p.osuProviderList.add(osu);
                         }
                     }
+
                     return p;
                 }
 
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
index 18a8f1e..f40dc4f 100644
--- a/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
@@ -94,10 +94,10 @@
             sb.append(" serverUri: ").append(serverUri);
         sb.append(" osuMethod: ").append(osuMethod);
         if (iconFileName != null) {
-            sb.append(" icon: [").append(iconWidth).append("x")
+            sb.append(" icon: <").append(iconWidth).append("x")
                     .append(iconHeight).append(" ")
                     .append(iconType).append(" ")
-                    .append(iconFileName);
+                    .append(iconFileName).append(">");
         }
         if (osuNai != null)
             sb.append(" osuNai: ").append(osuNai);
@@ -113,16 +113,16 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeValue(ssid);
-        out.writeValue(friendlyName);
-        out.writeValue(serverUri);
+        out.writeString(ssid);
+        out.writeString(friendlyName);
+        out.writeString(serverUri);
         out.writeInt(osuMethod);
         out.writeInt(iconWidth);
         out.writeInt(iconHeight);
-        out.writeValue(iconType);
-        out.writeValue(iconFileName);
-        out.writeValue(osuNai);
-        out.writeValue(osuService);
+        out.writeString(iconType);
+        out.writeString(iconFileName);
+        out.writeString(osuNai);
+        out.writeString(osuService);
         // TODO: icon image?
     }
 
@@ -131,16 +131,16 @@
                 @Override
                 public WifiPasspointOsuProvider createFromParcel(Parcel in) {
                     WifiPasspointOsuProvider osu = new WifiPasspointOsuProvider();
-                    osu.ssid = (String) in.readValue(String.class.getClassLoader());
-                    osu.friendlyName = (String) in.readValue(String.class.getClassLoader());
-                    osu.serverUri = (String) in.readValue(String.class.getClassLoader());
+                    osu.ssid = in.readString();
+                    osu.friendlyName = in.readString();
+                    osu.serverUri = in.readString();
                     osu.osuMethod = in.readInt();
                     osu.iconWidth = in.readInt();
                     osu.iconHeight = in.readInt();
-                    osu.iconType = (String) in.readValue(String.class.getClassLoader());
-                    osu.iconFileName = (String) in.readValue(String.class.getClassLoader());
-                    osu.osuNai = (String) in.readValue(String.class.getClassLoader());
-                    osu.osuService = (String) in.readValue(String.class.getClassLoader());
+                    osu.iconType = in.readString();
+                    osu.iconFileName = in.readString();
+                    osu.osuNai = in.readString();
+                    osu.osuService = in.readString();
                     return osu;
                 }