Merge "Glop ColorFilter & VertexBuffer support, initial enable"
diff --git a/Android.mk b/Android.mk
index 2d0d1f7..a20798d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -202,6 +202,7 @@
 	core/java/android/os/INetworkActivityListener.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
 	core/java/android/os/IPermissionController.aidl \
+	core/java/android/os/IProcessInfoService.aidl \
 	core/java/android/os/IPowerManager.aidl \
 	core/java/android/os/IRemoteCallback.aidl \
 	core/java/android/os/ISchedulingPolicyService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 9c26faa..1abcdb1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -529,6 +529,7 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
+    field public static final int end = 16843997; // 0x10104dd
     field public static final int endColor = 16843166; // 0x101019e
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
@@ -1014,6 +1015,7 @@
     field public static final int resizeClip = 16843983; // 0x10104cf
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
+    field public static final int resizeableActivity = 16843995; // 0x10104db
     field public static final int resource = 16842789; // 0x1010025
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -1127,6 +1129,7 @@
     field public static final int stackFromBottom = 16843005; // 0x10100fd
     field public static final int stackViewStyle = 16843838; // 0x101043e
     field public static final int starStyle = 16842882; // 0x1010082
+    field public static final int start = 16843996; // 0x10104dc
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
@@ -1316,6 +1319,8 @@
     field public static final int topRightRadius = 16843178; // 0x10101aa
     field public static final int touchscreenBlocksFocus = 16843919; // 0x101048f
     field public static final int track = 16843631; // 0x101036f
+    field public static final int trackTint = 16843993; // 0x10104d9
+    field public static final int trackTintMode = 16843994; // 0x10104da
     field public static final int transcriptMode = 16843008; // 0x1010100
     field public static final int transformPivotX = 16843552; // 0x1010320
     field public static final int transformPivotY = 16843553; // 0x1010321
@@ -1407,6 +1412,7 @@
     field public static final int windowExitTransition = 16843832; // 0x1010438
     field public static final int windowFrame = 16842837; // 0x1010055
     field public static final int windowFullscreen = 16843277; // 0x101020d
+    field public static final int windowHasLightStatusBar = 16843998; // 0x10104de
     field public static final int windowHideAnimation = 16842935; // 0x10100b7
     field public static final int windowIsFloating = 16842839; // 0x1010057
     field public static final int windowIsTranslucent = 16842840; // 0x1010058
@@ -3914,6 +3920,46 @@
     field public java.lang.String serviceDetails;
   }
 
+  public final class AssistData implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.app.AssistData getAssistData(android.os.Bundle);
+    method public void getWindowAt(int, android.app.AssistData.ViewNode);
+    method public int getWindowCount();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ASSIST_KEY = "android:assist";
+    field public static final android.os.Parcelable.Creator<android.app.AssistData> CREATOR;
+  }
+
+  public static class AssistData.ViewNode {
+    ctor public AssistData.ViewNode();
+    method public void getChildAt(int, android.app.AssistData.ViewNode);
+    method public int getChildCount();
+    method public java.lang.String getClassName();
+    method public java.lang.String getContentDescription();
+    method public android.os.Bundle getExtras();
+    method public int getHeight();
+    method public java.lang.String getHint();
+    method public int getLeft();
+    method public int getScrollX();
+    method public int getScrollY();
+    method public java.lang.String getText();
+    method public int getTextSelectionEnd();
+    method public int getTextSelectionStart();
+    method public int getTop();
+    method public int getVisibility();
+    method public int getWidth();
+    method public boolean isAccessibilityFocused();
+    method public boolean isActivated();
+    method public boolean isCheckable();
+    method public boolean isChecked();
+    method public boolean isClickable();
+    method public boolean isEnabled();
+    method public boolean isFocusable();
+    method public boolean isFocused();
+    method public boolean isLongClickable();
+    method public boolean isSelected();
+  }
+
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
     ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
     ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
@@ -4767,6 +4813,37 @@
     method public android.app.Notification.Builder setWhen(long);
   }
 
+  public static final class Notification.CarExtender implements android.app.Notification.Extender {
+    ctor public Notification.CarExtender();
+    ctor public Notification.CarExtender(android.app.Notification);
+    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
+    method public int getColor();
+    method public android.graphics.Bitmap getLargeIcon();
+    method public android.app.Notification.CarExtender.UnreadConversation getUnreadConversation();
+    method public android.app.Notification.CarExtender setColor(int);
+    method public android.app.Notification.CarExtender setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.CarExtender setUnreadConversation(android.app.Notification.CarExtender.UnreadConversation);
+  }
+
+  public static class Notification.CarExtender.Builder {
+    ctor public Notification.CarExtender.Builder(java.lang.String);
+    method public android.app.Notification.CarExtender.Builder addMessage(java.lang.String);
+    method public android.app.Notification.CarExtender.UnreadConversation build();
+    method public android.app.Notification.CarExtender.Builder setLatestTimestamp(long);
+    method public android.app.Notification.CarExtender.Builder setReadPendingIntent(android.app.PendingIntent);
+    method public android.app.Notification.CarExtender.Builder setReplyAction(android.app.PendingIntent, android.app.RemoteInput);
+  }
+
+  public static class Notification.CarExtender.UnreadConversation {
+    method public long getLatestTimestamp();
+    method public java.lang.String[] getMessages();
+    method public java.lang.String getParticipant();
+    method public java.lang.String[] getParticipants();
+    method public android.app.PendingIntent getReadPendingIntent();
+    method public android.app.RemoteInput getRemoteInput();
+    method public android.app.PendingIntent getReplyPendingIntent();
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
@@ -5453,6 +5530,7 @@
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
+    field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
@@ -11911,6 +11989,9 @@
     method public android.graphics.drawable.Drawable findDrawableByLayerId(int);
     method public android.graphics.drawable.Drawable getDrawable(int);
     method public int getId(int);
+    method public int getLayerGravity(int);
+    method public int getLayerHeight(int);
+    method public int getLayerWidth(int);
     method public int getNumberOfLayers();
     method public int getOpacity();
     method public int getPaddingMode();
@@ -11920,7 +12001,10 @@
     method public void setColorFilter(android.graphics.ColorFilter);
     method public boolean setDrawableByLayerId(int, android.graphics.drawable.Drawable);
     method public void setId(int, int);
+    method public void setLayerGravity(int, int);
     method public void setLayerInset(int, int, int, int, int);
+    method public void setLayerInsetRelative(int, int, int, int, int);
+    method public void setLayerSize(int, int, int);
     method public void setOpacity(int);
     method public void setPaddingMode(int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
@@ -12661,11 +12745,14 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>[]> CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> CONTROL_AE_COMPENSATION_RANGE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Rational> CONTROL_AE_COMPENSATION_STEP;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AE_LOCK_AVAILABLE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AF_AVAILABLE_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_EFFECTS;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_SCENE_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AWB_AVAILABLE_MODES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AWB_LOCK_AVAILABLE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
@@ -12684,6 +12771,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_RAW;
@@ -12901,13 +12989,16 @@
     field public static final int LENS_STATE_STATIONARY = 0; // 0x0
     field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
     field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2
+    field public static final int NOISE_REDUCTION_MODE_MINIMAL = 3; // 0x3
     field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
     field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
     field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
@@ -13013,6 +13104,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -13090,6 +13182,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
     field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -14129,6 +14222,7 @@
     method public boolean isMicrophoneMute();
     method public boolean isMusicActive();
     method public boolean isSpeakerphoneOn();
+    method public boolean isStreamMute(int);
     method public boolean isVolumeFixed();
     method public deprecated boolean isWiredHeadsetOn();
     method public void loadSoundEffects();
@@ -14147,8 +14241,8 @@
     method public void setRingerMode(int);
     method public deprecated void setRouting(int, int, int);
     method public void setSpeakerphoneOn(boolean);
-    method public void setStreamMute(int, boolean);
-    method public void setStreamSolo(int, boolean);
+    method public deprecated void setStreamMute(int, boolean);
+    method public deprecated void setStreamSolo(int, boolean);
     method public void setStreamVolume(int, int, int);
     method public deprecated void setVibrateSetting(int, int);
     method public deprecated void setWiredHeadsetOn(boolean);
@@ -14166,8 +14260,11 @@
     field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
     field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
     field public static final int ADJUST_LOWER = -1; // 0xffffffff
+    field public static final int ADJUST_MUTE = -100; // 0xffffff9c
     field public static final int ADJUST_RAISE = 1; // 0x1
     field public static final int ADJUST_SAME = 0; // 0x0
+    field public static final int ADJUST_TOGGLE_MUTE = 101; // 0x65
+    field public static final int ADJUST_UNMUTE = 100; // 0x64
     field public static final int AUDIOFOCUS_GAIN = 1; // 0x1
     field public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; // 0x2
     field public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4; // 0x4
@@ -17578,7 +17675,6 @@
     method public static javax.net.SocketFactory getDefault(int);
     method public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache);
     method public java.lang.String[] getDefaultCipherSuites();
-    method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
     method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
     method public byte[] getNpnSelectedProtocol(java.net.Socket);
     method public java.lang.String[] getSupportedCipherSuites();
@@ -23178,6 +23274,7 @@
   public final class PrintAttributes implements android.os.Parcelable {
     method public int describeContents();
     method public int getColorMode();
+    method public int getDuplexMode();
     method public android.print.PrintAttributes.MediaSize getMediaSize();
     method public android.print.PrintAttributes.Margins getMinMargins();
     method public android.print.PrintAttributes.Resolution getResolution();
@@ -23185,12 +23282,16 @@
     field public static final int COLOR_MODE_COLOR = 2; // 0x2
     field public static final int COLOR_MODE_MONOCHROME = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.print.PrintAttributes> CREATOR;
+    field public static final int DUPLEX_MODE_LONG_EDGE = 2; // 0x2
+    field public static final int DUPLEX_MODE_NONE = 1; // 0x1
+    field public static final int DUPLEX_MODE_SHORT_EDGE = 4; // 0x4
   }
 
   public static final class PrintAttributes.Builder {
     ctor public PrintAttributes.Builder();
     method public android.print.PrintAttributes build();
     method public android.print.PrintAttributes.Builder setColorMode(int);
+    method public android.print.PrintAttributes.Builder setDuplexMode(int);
     method public android.print.PrintAttributes.Builder setMediaSize(android.print.PrintAttributes.MediaSize);
     method public android.print.PrintAttributes.Builder setMinMargins(android.print.PrintAttributes.Margins);
     method public android.print.PrintAttributes.Builder setResolution(android.print.PrintAttributes.Resolution);
@@ -23408,6 +23509,7 @@
     method public int describeContents();
     method public int getColorModes();
     method public android.print.PrintAttributes getDefaults();
+    method public int getDuplexModes();
     method public java.util.List<android.print.PrintAttributes.MediaSize> getMediaSizes();
     method public android.print.PrintAttributes.Margins getMinMargins();
     method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
@@ -23421,6 +23523,7 @@
     method public android.print.PrinterCapabilitiesInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
     method public android.print.PrinterCapabilitiesInfo build();
     method public android.print.PrinterCapabilitiesInfo.Builder setColorModes(int, int);
+    method public android.print.PrinterCapabilitiesInfo.Builder setDuplexModes(int, int);
     method public android.print.PrinterCapabilitiesInfo.Builder setMinMargins(android.print.PrintAttributes.Margins);
   }
 
@@ -24617,6 +24720,7 @@
     field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
     field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
     field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
+    field public static final java.lang.String QUERY_PARAMETER_VCARD_NO_PHOTO = "no_photo";
   }
 
   public static final class ContactsContract.Contacts.AggregationSuggestions implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
@@ -24931,6 +25035,7 @@
     method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
     field public static final java.lang.String ACTION_QUICK_CONTACT = "android.provider.action.QUICK_CONTACT";
     field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES";
+    field public static final java.lang.String EXTRA_MODE = "android.provider.extra.MODE";
     field public static final int MODE_LARGE = 3; // 0x3
     field public static final int MODE_MEDIUM = 2; // 0x2
     field public static final int MODE_SMALL = 1; // 0x1
@@ -28560,8 +28665,65 @@
 
 package android.telecom {
 
+  public class PhoneAccount implements android.os.Parcelable {
+    method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
+    method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
+    method public int describeContents();
+    method public android.telecom.PhoneAccountHandle getAccountHandle();
+    method public android.net.Uri getAddress();
+    method public int getCapabilities();
+    method public int getHighlightColor();
+    method public android.graphics.Bitmap getIconBitmap();
+    method public java.lang.String getIconPackageName();
+    method public int getIconResId();
+    method public int getIconTint();
+    method public java.lang.CharSequence getLabel();
+    method public java.lang.CharSequence getShortDescription();
+    method public android.net.Uri getSubscriptionAddress();
+    method public java.util.List<java.lang.String> getSupportedUriSchemes();
+    method public boolean hasCapabilities(int);
+    method public boolean supportsUriScheme(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
+    field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
+    field public static final int NO_ICON_TINT = 0; // 0x0
+    field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
+    field public static final java.lang.String SCHEME_SIP = "sip";
+    field public static final java.lang.String SCHEME_TEL = "tel";
+    field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
+  }
+
+  public static class PhoneAccount.Builder {
+    ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
+    ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
+    method public android.telecom.PhoneAccount build();
+    method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
+    method public android.telecom.PhoneAccount.Builder setCapabilities(int);
+    method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.Bitmap);
+    method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
+    method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
+    method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
+  }
+
+  public class PhoneAccountHandle implements android.os.Parcelable {
+    ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
+    method public int describeContents();
+    method public android.content.ComponentName getComponentName();
+    method public java.lang.String getId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR;
+  }
+
   public class TelecomManager {
     method public void cancelMissedCallsNotification();
+    method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public boolean handleMmi(java.lang.String);
     method public boolean isInCall();
     method public void showInCallScreen(boolean);
@@ -28570,7 +28732,10 @@
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
+    field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
+    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -28579,6 +28744,34 @@
     field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
   }
 
+  public class VideoProfile implements android.os.Parcelable {
+    ctor public VideoProfile(int);
+    ctor public VideoProfile(int, int);
+    method public int describeContents();
+    method public int getQuality();
+    method public int getVideoState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile> CREATOR;
+    field public static final int QUALITY_DEFAULT = 4; // 0x4
+    field public static final int QUALITY_HIGH = 1; // 0x1
+    field public static final int QUALITY_LOW = 3; // 0x3
+    field public static final int QUALITY_MEDIUM = 2; // 0x2
+  }
+
+  public static class VideoProfile.VideoState {
+    ctor public VideoProfile.VideoState();
+    method public static boolean isAudioOnly(int);
+    method public static boolean isBidirectional(int);
+    method public static boolean isPaused(int);
+    method public static boolean isReceptionEnabled(int);
+    method public static boolean isTransmissionEnabled(int);
+    field public static final int AUDIO_ONLY = 0; // 0x0
+    field public static final int BIDIRECTIONAL = 3; // 0x3
+    field public static final int PAUSED = 4; // 0x4
+    field public static final int RX_ENABLED = 2; // 0x2
+    field public static final int TX_ENABLED = 1; // 0x1
+  }
+
 }
 
 package android.telephony {
@@ -28772,6 +28965,7 @@
 
   public class PhoneNumberUtils {
     ctor public PhoneNumberUtils();
+    method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
     method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
     method public static java.lang.String calledPartyBCDToString(byte[], int, int);
     method public static boolean compare(java.lang.String, java.lang.String);
@@ -28789,6 +28983,8 @@
     method public static java.lang.String formatNumberToRFC3966(java.lang.String, java.lang.String);
     method public static deprecated int getFormatTypeForLocale(java.util.Locale);
     method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+    method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
+    method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String getStrippedReversed(java.lang.String);
     method public static final boolean is12Key(char);
     method public static final boolean isDialable(char);
@@ -32404,6 +32600,7 @@
     method public java.lang.Object getTag();
     method public abstract java.lang.CharSequence getTitle();
     method public boolean getTitleOptionalHint();
+    method public int getType();
     method public abstract void invalidate();
     method public boolean isTitleOptional();
     method public abstract void setCustomView(android.view.View);
@@ -32413,6 +32610,9 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract void setTitle(int);
     method public void setTitleOptionalHint(boolean);
+    method public void setType(int);
+    field public static final int TYPE_FLOATING = 1; // 0x1
+    field public static final int TYPE_PRIMARY = 0; // 0x0
   }
 
   public static abstract interface ActionMode.Callback {
@@ -33763,6 +33963,7 @@
     method public android.view.View focusSearch(int);
     method public void forceLayout();
     method public static int generateViewId();
+    method public java.lang.CharSequence getAccessibilityClassName();
     method public int getAccessibilityLiveRegion();
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
     method public int getAccessibilityTraversalAfter();
@@ -33988,6 +34189,7 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void onProvideAssistData(android.view.ViewAssistData, android.os.Bundle);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -34263,6 +34465,7 @@
     field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
     field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
     field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+    field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
     field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
@@ -34389,6 +34592,17 @@
     method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
+  public abstract class ViewAssistData {
+    ctor public ViewAssistData();
+    method public abstract java.lang.CharSequence getHint();
+    method public abstract java.lang.CharSequence getText();
+    method public abstract int getTextSelectionEnd();
+    method public abstract int getTextSelectionStart();
+    method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setText(java.lang.CharSequence);
+    method public abstract void setText(java.lang.CharSequence, int, int);
+  }
+
   public class ViewConfiguration {
     ctor public deprecated ViewConfiguration();
     method public static android.view.ViewConfiguration get(android.content.Context);
@@ -38416,6 +38630,8 @@
     method public void setClippingEnabled(boolean);
     method public void setContentView(android.view.View);
     method public void setElevation(float);
+    method public void setEnterTransition(android.transition.Transition);
+    method public void setExitTransition(android.transition.Transition);
     method public void setFocusable(boolean);
     method public void setHeight(int);
     method public void setIgnoreCheekPress();
@@ -39017,7 +39233,11 @@
     method public java.lang.CharSequence getTextOn();
     method public android.graphics.drawable.Drawable getThumbDrawable();
     method public int getThumbTextPadding();
+    method public android.content.res.ColorStateList getThumbTintList();
+    method public android.graphics.PorterDuff.Mode getThumbTintMode();
     method public android.graphics.drawable.Drawable getTrackDrawable();
+    method public android.content.res.ColorStateList getTrackTintList();
+    method public android.graphics.PorterDuff.Mode getTrackTintMode();
     method public void onMeasure(int, int);
     method public void setShowText(boolean);
     method public void setSplitTrack(boolean);
@@ -39031,8 +39251,12 @@
     method public void setThumbDrawable(android.graphics.drawable.Drawable);
     method public void setThumbResource(int);
     method public void setThumbTextPadding(int);
+    method public void setThumbTintList(android.content.res.ColorStateList);
+    method public void setThumbTintMode(android.graphics.PorterDuff.Mode);
     method public void setTrackDrawable(android.graphics.drawable.Drawable);
     method public void setTrackResource(int);
+    method public void setTrackTintList(android.content.res.ColorStateList);
+    method public void setTrackTintMode(android.graphics.PorterDuff.Mode);
   }
 
   public class TabHost extends android.widget.FrameLayout implements android.view.ViewTreeObserver.OnTouchModeChangeListener {
diff --git a/api/removed.txt b/api/removed.txt
index 1b69ee8..9322973 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -6,6 +6,14 @@
 
 }
 
+package android.net {
+
+  public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
+    method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
+  }
+
+}
+
 package android.os {
 
   public final class PowerManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index 62932fd..d971ce7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -601,6 +601,7 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
+    field public static final int end = 16843997; // 0x10104dd
     field public static final int endColor = 16843166; // 0x101019e
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
@@ -1086,6 +1087,7 @@
     field public static final int resizeClip = 16843983; // 0x10104cf
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
+    field public static final int resizeableActivity = 16843995; // 0x10104db
     field public static final int resource = 16842789; // 0x1010025
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -1203,6 +1205,7 @@
     field public static final int stackFromBottom = 16843005; // 0x10100fd
     field public static final int stackViewStyle = 16843838; // 0x101043e
     field public static final int starStyle = 16842882; // 0x1010082
+    field public static final int start = 16843996; // 0x10104dc
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
@@ -1392,6 +1395,8 @@
     field public static final int topRightRadius = 16843178; // 0x10101aa
     field public static final int touchscreenBlocksFocus = 16843919; // 0x101048f
     field public static final int track = 16843631; // 0x101036f
+    field public static final int trackTint = 16843993; // 0x10104d9
+    field public static final int trackTintMode = 16843994; // 0x10104da
     field public static final int transcriptMode = 16843008; // 0x1010100
     field public static final int transformPivotX = 16843552; // 0x1010320
     field public static final int transformPivotY = 16843553; // 0x1010321
@@ -1483,6 +1488,7 @@
     field public static final int windowExitTransition = 16843832; // 0x1010438
     field public static final int windowFrame = 16842837; // 0x1010055
     field public static final int windowFullscreen = 16843277; // 0x101020d
+    field public static final int windowHasLightStatusBar = 16843998; // 0x10104de
     field public static final int windowHideAnimation = 16842935; // 0x10100b7
     field public static final int windowIsFloating = 16842839; // 0x1010057
     field public static final int windowIsTranslucent = 16842840; // 0x1010058
@@ -4004,6 +4010,46 @@
     field public java.lang.String serviceDetails;
   }
 
+  public final class AssistData implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.app.AssistData getAssistData(android.os.Bundle);
+    method public void getWindowAt(int, android.app.AssistData.ViewNode);
+    method public int getWindowCount();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ASSIST_KEY = "android:assist";
+    field public static final android.os.Parcelable.Creator<android.app.AssistData> CREATOR;
+  }
+
+  public static class AssistData.ViewNode {
+    ctor public AssistData.ViewNode();
+    method public void getChildAt(int, android.app.AssistData.ViewNode);
+    method public int getChildCount();
+    method public java.lang.String getClassName();
+    method public java.lang.String getContentDescription();
+    method public android.os.Bundle getExtras();
+    method public int getHeight();
+    method public java.lang.String getHint();
+    method public int getLeft();
+    method public int getScrollX();
+    method public int getScrollY();
+    method public java.lang.String getText();
+    method public int getTextSelectionEnd();
+    method public int getTextSelectionStart();
+    method public int getTop();
+    method public int getVisibility();
+    method public int getWidth();
+    method public boolean isAccessibilityFocused();
+    method public boolean isActivated();
+    method public boolean isCheckable();
+    method public boolean isChecked();
+    method public boolean isClickable();
+    method public boolean isEnabled();
+    method public boolean isFocusable();
+    method public boolean isFocused();
+    method public boolean isLongClickable();
+    method public boolean isSelected();
+  }
+
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
     ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
     ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
@@ -4857,6 +4903,37 @@
     method public android.app.Notification.Builder setWhen(long);
   }
 
+  public static final class Notification.CarExtender implements android.app.Notification.Extender {
+    ctor public Notification.CarExtender();
+    ctor public Notification.CarExtender(android.app.Notification);
+    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
+    method public int getColor();
+    method public android.graphics.Bitmap getLargeIcon();
+    method public android.app.Notification.CarExtender.UnreadConversation getUnreadConversation();
+    method public android.app.Notification.CarExtender setColor(int);
+    method public android.app.Notification.CarExtender setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.CarExtender setUnreadConversation(android.app.Notification.CarExtender.UnreadConversation);
+  }
+
+  public static class Notification.CarExtender.Builder {
+    ctor public Notification.CarExtender.Builder(java.lang.String);
+    method public android.app.Notification.CarExtender.Builder addMessage(java.lang.String);
+    method public android.app.Notification.CarExtender.UnreadConversation build();
+    method public android.app.Notification.CarExtender.Builder setLatestTimestamp(long);
+    method public android.app.Notification.CarExtender.Builder setReadPendingIntent(android.app.PendingIntent);
+    method public android.app.Notification.CarExtender.Builder setReplyAction(android.app.PendingIntent, android.app.RemoteInput);
+  }
+
+  public static class Notification.CarExtender.UnreadConversation {
+    method public long getLatestTimestamp();
+    method public java.lang.String[] getMessages();
+    method public java.lang.String getParticipant();
+    method public java.lang.String[] getParticipants();
+    method public android.app.PendingIntent getReadPendingIntent();
+    method public android.app.RemoteInput getRemoteInput();
+    method public android.app.PendingIntent getReplyPendingIntent();
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
@@ -5334,6 +5411,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clearWallpaper();
     method public void clearWallpaperOffsets(android.os.IBinder);
     method public void forgetLoadedWallpaper();
     method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -5354,6 +5432,7 @@
     method public void setDisplayPadding(android.graphics.Rect);
     method public void setResource(int) throws java.io.IOException;
     method public void setStream(java.io.InputStream) throws java.io.IOException;
+    method public boolean setWallpaperComponent(android.content.ComponentName);
     method public void setWallpaperOffsetSteps(float, float);
     method public void setWallpaperOffsets(android.os.IBinder, float, float);
     method public void suggestDesiredDimensions(int, int);
@@ -5554,6 +5633,7 @@
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
+    field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
@@ -12179,6 +12259,9 @@
     method public android.graphics.drawable.Drawable findDrawableByLayerId(int);
     method public android.graphics.drawable.Drawable getDrawable(int);
     method public int getId(int);
+    method public int getLayerGravity(int);
+    method public int getLayerHeight(int);
+    method public int getLayerWidth(int);
     method public int getNumberOfLayers();
     method public int getOpacity();
     method public int getPaddingMode();
@@ -12188,7 +12271,10 @@
     method public void setColorFilter(android.graphics.ColorFilter);
     method public boolean setDrawableByLayerId(int, android.graphics.drawable.Drawable);
     method public void setId(int, int);
+    method public void setLayerGravity(int, int);
     method public void setLayerInset(int, int, int, int, int);
+    method public void setLayerInsetRelative(int, int, int, int, int);
+    method public void setLayerSize(int, int, int);
     method public void setOpacity(int);
     method public void setPaddingMode(int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
@@ -12929,11 +13015,14 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>[]> CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Integer>> CONTROL_AE_COMPENSATION_RANGE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Rational> CONTROL_AE_COMPENSATION_STEP;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AE_LOCK_AVAILABLE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AF_AVAILABLE_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_EFFECTS;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_SCENE_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AWB_AVAILABLE_MODES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AWB_LOCK_AVAILABLE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
@@ -12952,6 +13041,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_RAW;
@@ -13169,13 +13259,16 @@
     field public static final int LENS_STATE_STATIONARY = 0; // 0x0
     field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
     field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2
+    field public static final int NOISE_REDUCTION_MODE_MINIMAL = 3; // 0x3
     field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
     field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
     field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
@@ -13281,6 +13374,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -13358,6 +13452,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
     field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -15107,6 +15202,7 @@
     method public boolean isMicrophoneMute();
     method public boolean isMusicActive();
     method public boolean isSpeakerphoneOn();
+    method public boolean isStreamMute(int);
     method public boolean isVolumeFixed();
     method public deprecated boolean isWiredHeadsetOn();
     method public void loadSoundEffects();
@@ -15128,8 +15224,8 @@
     method public void setRingerMode(int);
     method public deprecated void setRouting(int, int, int);
     method public void setSpeakerphoneOn(boolean);
-    method public void setStreamMute(int, boolean);
-    method public void setStreamSolo(int, boolean);
+    method public deprecated void setStreamMute(int, boolean);
+    method public deprecated void setStreamSolo(int, boolean);
     method public void setStreamVolume(int, int, int);
     method public deprecated void setVibrateSetting(int, int);
     method public deprecated void setWiredHeadsetOn(boolean);
@@ -15148,8 +15244,11 @@
     field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
     field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
     field public static final int ADJUST_LOWER = -1; // 0xffffffff
+    field public static final int ADJUST_MUTE = -100; // 0xffffff9c
     field public static final int ADJUST_RAISE = 1; // 0x1
     field public static final int ADJUST_SAME = 0; // 0x0
+    field public static final int ADJUST_TOGGLE_MUTE = 101; // 0x65
+    field public static final int ADJUST_UNMUTE = 100; // 0x64
     field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
     field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
     field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
@@ -18838,7 +18937,6 @@
     method public static javax.net.SocketFactory getDefault(int);
     method public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache);
     method public java.lang.String[] getDefaultCipherSuites();
-    method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
     method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
     method public byte[] getNpnSelectedProtocol(java.net.Socket);
     method public java.lang.String[] getSupportedCipherSuites();
@@ -24767,6 +24865,7 @@
   public final class PrintAttributes implements android.os.Parcelable {
     method public int describeContents();
     method public int getColorMode();
+    method public int getDuplexMode();
     method public android.print.PrintAttributes.MediaSize getMediaSize();
     method public android.print.PrintAttributes.Margins getMinMargins();
     method public android.print.PrintAttributes.Resolution getResolution();
@@ -24774,12 +24873,16 @@
     field public static final int COLOR_MODE_COLOR = 2; // 0x2
     field public static final int COLOR_MODE_MONOCHROME = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.print.PrintAttributes> CREATOR;
+    field public static final int DUPLEX_MODE_LONG_EDGE = 2; // 0x2
+    field public static final int DUPLEX_MODE_NONE = 1; // 0x1
+    field public static final int DUPLEX_MODE_SHORT_EDGE = 4; // 0x4
   }
 
   public static final class PrintAttributes.Builder {
     ctor public PrintAttributes.Builder();
     method public android.print.PrintAttributes build();
     method public android.print.PrintAttributes.Builder setColorMode(int);
+    method public android.print.PrintAttributes.Builder setDuplexMode(int);
     method public android.print.PrintAttributes.Builder setMediaSize(android.print.PrintAttributes.MediaSize);
     method public android.print.PrintAttributes.Builder setMinMargins(android.print.PrintAttributes.Margins);
     method public android.print.PrintAttributes.Builder setResolution(android.print.PrintAttributes.Resolution);
@@ -24997,6 +25100,7 @@
     method public int describeContents();
     method public int getColorModes();
     method public android.print.PrintAttributes getDefaults();
+    method public int getDuplexModes();
     method public java.util.List<android.print.PrintAttributes.MediaSize> getMediaSizes();
     method public android.print.PrintAttributes.Margins getMinMargins();
     method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
@@ -25010,6 +25114,7 @@
     method public android.print.PrinterCapabilitiesInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
     method public android.print.PrinterCapabilitiesInfo build();
     method public android.print.PrinterCapabilitiesInfo.Builder setColorModes(int, int);
+    method public android.print.PrinterCapabilitiesInfo.Builder setDuplexModes(int, int);
     method public android.print.PrinterCapabilitiesInfo.Builder setMinMargins(android.print.PrintAttributes.Margins);
   }
 
@@ -26206,6 +26311,7 @@
     field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
     field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
     field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
+    field public static final java.lang.String QUERY_PARAMETER_VCARD_NO_PHOTO = "no_photo";
   }
 
   public static final class ContactsContract.Contacts.AggregationSuggestions implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
@@ -26520,6 +26626,7 @@
     method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
     field public static final java.lang.String ACTION_QUICK_CONTACT = "android.provider.action.QUICK_CONTACT";
     field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES";
+    field public static final java.lang.String EXTRA_MODE = "android.provider.extra.MODE";
     field public static final int MODE_LARGE = 3; // 0x3
     field public static final int MODE_MEDIUM = 2; // 0x2
     field public static final int MODE_SMALL = 1; // 0x1
@@ -27221,6 +27328,7 @@
     field public static final java.lang.String SHOW_PROCESSES = "show_processes";
     field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
     field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_global_version";
+    field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on";
     field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
     field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
     field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
@@ -30398,6 +30506,7 @@
     method public final int getState();
     method public final android.telecom.StatusHints getStatusHints();
     method public final boolean isRingbackRequested();
+    method protected void notifyConferenceStarted();
     method public void onAbort();
     method public void onAnswer();
     method public void onAudioStateChanged(android.telecom.AudioState);
@@ -30423,6 +30532,7 @@
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setInitialized();
     method public final void setInitializing();
+    method public final void setNextPostDialChar(char);
     method public final void setOnHold();
     method public final void setPostDialWait(java.lang.String);
     method public final void setRingbackRequested(boolean);
@@ -30562,10 +30672,14 @@
     method public java.util.List<java.lang.String> getSupportedUriSchemes();
     method public boolean hasCapabilities(int);
     method public boolean supportsUriScheme(java.lang.String);
+    method public android.telecom.PhoneAccount.Builder toBuilder();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_CALL_PROVIDER = 2; // 0x2
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
+    field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
     field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
     field public static final int NO_ICON_TINT = 0; // 0x0
@@ -30578,7 +30692,9 @@
   public static class PhoneAccount.Builder {
     ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
     ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
+    method public android.telecom.PhoneAccount.Builder addSupportedUriScheme(java.lang.String);
     method public android.telecom.PhoneAccount build();
+    method public android.telecom.PhoneAccount.Builder setAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setCapabilities(int);
     method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
@@ -30594,9 +30710,11 @@
 
   public class PhoneAccountHandle implements android.os.Parcelable {
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
+    ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String, android.os.UserHandle);
     method public int describeContents();
     method public android.content.ComponentName getComponentName();
     method public java.lang.String getId();
+    method public android.os.UserHandle getUserHandle();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR;
   }
@@ -30732,6 +30850,7 @@
     field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
     field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -30740,6 +30859,34 @@
     field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
   }
 
+  public class VideoProfile implements android.os.Parcelable {
+    ctor public VideoProfile(int);
+    ctor public VideoProfile(int, int);
+    method public int describeContents();
+    method public int getQuality();
+    method public int getVideoState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile> CREATOR;
+    field public static final int QUALITY_DEFAULT = 4; // 0x4
+    field public static final int QUALITY_HIGH = 1; // 0x1
+    field public static final int QUALITY_LOW = 3; // 0x3
+    field public static final int QUALITY_MEDIUM = 2; // 0x2
+  }
+
+  public static class VideoProfile.VideoState {
+    ctor public VideoProfile.VideoState();
+    method public static boolean isAudioOnly(int);
+    method public static boolean isBidirectional(int);
+    method public static boolean isPaused(int);
+    method public static boolean isReceptionEnabled(int);
+    method public static boolean isTransmissionEnabled(int);
+    field public static final int AUDIO_ONLY = 0; // 0x0
+    field public static final int BIDIRECTIONAL = 3; // 0x3
+    field public static final int PAUSED = 4; // 0x4
+    field public static final int RX_ENABLED = 2; // 0x2
+    field public static final int TX_ENABLED = 1; // 0x1
+  }
+
 }
 
 package android.telephony {
@@ -30933,6 +31080,7 @@
 
   public class PhoneNumberUtils {
     ctor public PhoneNumberUtils();
+    method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
     method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
     method public static java.lang.String calledPartyBCDToString(byte[], int, int);
     method public static boolean compare(java.lang.String, java.lang.String);
@@ -30950,6 +31098,8 @@
     method public static java.lang.String formatNumberToRFC3966(java.lang.String, java.lang.String);
     method public static deprecated int getFormatTypeForLocale(java.util.Locale);
     method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+    method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
+    method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String getStrippedReversed(java.lang.String);
     method public static final boolean is12Key(char);
     method public static final boolean isDialable(char);
@@ -34603,6 +34753,7 @@
     method public java.lang.Object getTag();
     method public abstract java.lang.CharSequence getTitle();
     method public boolean getTitleOptionalHint();
+    method public int getType();
     method public abstract void invalidate();
     method public boolean isTitleOptional();
     method public abstract void setCustomView(android.view.View);
@@ -34612,6 +34763,9 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract void setTitle(int);
     method public void setTitleOptionalHint(boolean);
+    method public void setType(int);
+    field public static final int TYPE_FLOATING = 1; // 0x1
+    field public static final int TYPE_PRIMARY = 0; // 0x0
   }
 
   public static abstract interface ActionMode.Callback {
@@ -35962,6 +36116,7 @@
     method public android.view.View focusSearch(int);
     method public void forceLayout();
     method public static int generateViewId();
+    method public java.lang.CharSequence getAccessibilityClassName();
     method public int getAccessibilityLiveRegion();
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
     method public int getAccessibilityTraversalAfter();
@@ -36187,6 +36342,7 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void onProvideAssistData(android.view.ViewAssistData, android.os.Bundle);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -36462,6 +36618,7 @@
     field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
     field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
     field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+    field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
     field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
@@ -36588,6 +36745,17 @@
     method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
+  public abstract class ViewAssistData {
+    ctor public ViewAssistData();
+    method public abstract java.lang.CharSequence getHint();
+    method public abstract java.lang.CharSequence getText();
+    method public abstract int getTextSelectionEnd();
+    method public abstract int getTextSelectionStart();
+    method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setText(java.lang.CharSequence);
+    method public abstract void setText(java.lang.CharSequence, int, int);
+  }
+
   public class ViewConfiguration {
     ctor public deprecated ViewConfiguration();
     method public static android.view.ViewConfiguration get(android.content.Context);
@@ -37286,8 +37454,10 @@
     method public java.lang.String debug(java.lang.String);
     method public int describeContents();
     method public final java.lang.CharSequence getTitle();
+    method public final long getUserActivityTimeout();
     method public static boolean mayUseInputMethod(int);
     method public final void setTitle(java.lang.CharSequence);
+    method public final void setUserActivityTimeout(long);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ALPHA_CHANGED = 128; // 0x80
     field public static final int ANIMATION_CHANGED = 16; // 0x10
@@ -40911,6 +41081,8 @@
     method public void setClippingEnabled(boolean);
     method public void setContentView(android.view.View);
     method public void setElevation(float);
+    method public void setEnterTransition(android.transition.Transition);
+    method public void setExitTransition(android.transition.Transition);
     method public void setFocusable(boolean);
     method public void setHeight(int);
     method public void setIgnoreCheekPress();
@@ -41512,7 +41684,11 @@
     method public java.lang.CharSequence getTextOn();
     method public android.graphics.drawable.Drawable getThumbDrawable();
     method public int getThumbTextPadding();
+    method public android.content.res.ColorStateList getThumbTintList();
+    method public android.graphics.PorterDuff.Mode getThumbTintMode();
     method public android.graphics.drawable.Drawable getTrackDrawable();
+    method public android.content.res.ColorStateList getTrackTintList();
+    method public android.graphics.PorterDuff.Mode getTrackTintMode();
     method public void onMeasure(int, int);
     method public void setShowText(boolean);
     method public void setSplitTrack(boolean);
@@ -41526,8 +41702,12 @@
     method public void setThumbDrawable(android.graphics.drawable.Drawable);
     method public void setThumbResource(int);
     method public void setThumbTextPadding(int);
+    method public void setThumbTintList(android.content.res.ColorStateList);
+    method public void setThumbTintMode(android.graphics.PorterDuff.Mode);
     method public void setTrackDrawable(android.graphics.drawable.Drawable);
     method public void setTrackResource(int);
+    method public void setTrackTintList(android.content.res.ColorStateList);
+    method public void setTrackTintMode(android.graphics.PorterDuff.Mode);
   }
 
   public class TabHost extends android.widget.FrameLayout implements android.view.ViewTreeObserver.OnTouchModeChangeListener {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1b69ee8..9322973 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -6,6 +6,14 @@
 
 }
 
+package android.net {
+
+  public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
+    method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
+  }
+
+}
+
 package android.os {
 
   public final class PowerManager {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 2a0ed90..cf608a8 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -134,8 +134,9 @@
                 "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
                 "       am stack list\n" +
                 "       am stack info <STACK_ID>\n" +
-                "       am lock-task <TASK_ID>\n" +
-                "       am lock-task stop\n" +
+                "       am task lock <TASK_ID>\n" +
+                "       am task lock stop\n" +
+                "       am task resizeable <TASK_ID> [true|false]\n" +
                 "       am get-config\n" +
                 "\n" +
                 "am start: start an Activity.  Options are:\n" +
@@ -250,7 +251,11 @@
                 "\n" +
                 "am stack info: display the information about activity stack <STACK_ID>.\n" +
                 "\n" +
-                "am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
+                "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
+                "\n" +
+                "am task lock stop: end the current task lock\n" +
+                "\n" +
+                "am task resizeable: change if <TASK_ID> is resizeable (true) or not (false).\n" +
                 "\n" +
                 "am get-config: retrieve the configuration and any recent configurations\n" +
                 "  of the device\n" +
@@ -351,8 +356,8 @@
             runStopUser();
         } else if (op.equals("stack")) {
             runStack();
-        } else if (op.equals("lock-task")) {
-            runLockTask();
+        } else if (op.equals("task")) {
+            runTask();
         } else if (op.equals("get-config")) {
             runGetConfig();
         } else {
@@ -1735,6 +1740,22 @@
         int right = Integer.valueOf(rightStr);
         String bottomStr = nextArgRequired();
         int bottom = Integer.valueOf(bottomStr);
+        if (left < 0) {
+            System.err.println("Error: bad left arg: " + leftStr);
+            return;
+        }
+        if (top < 0) {
+            System.err.println("Error: bad top arg: " + topStr);
+            return;
+        }
+        if (right <= 0) {
+            System.err.println("Error: bad right arg: " + rightStr);
+            return;
+        }
+        if (bottom <= 0) {
+            System.err.println("Error: bad bottom arg: " + bottomStr);
+            return;
+        }
 
         try {
             mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
@@ -1762,7 +1783,19 @@
         }
     }
 
-    private void runLockTask() throws Exception {
+    private void runTask() throws Exception {
+        String op = nextArgRequired();
+        if (op.equals("lock")) {
+            runTaskLock();
+        } else if (op.equals("resizeable")) {
+            runTaskResizeable();
+        } else {
+            showError("Error: unknown command '" + op + "'");
+            return;
+        }
+    }
+
+    private void runTaskLock() throws Exception {
         String taskIdStr = nextArgRequired();
         try {
             if (taskIdStr.equals("stop")) {
@@ -1777,6 +1810,18 @@
         }
     }
 
+    private void runTaskResizeable() throws Exception {
+        final String taskIdStr = nextArgRequired();
+        final int taskId = Integer.valueOf(taskIdStr);
+        final String resizeableStr = nextArgRequired();
+        final boolean resizeable = Boolean.valueOf(resizeableStr);
+
+        try {
+            mAm.setTaskResizeable(taskId, resizeable);
+        } catch (RemoteException e) {
+        }
+    }
+
     private List<Configuration> getRecentConfigurations(int days) {
         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
                     Context.USAGE_STATS_SERVICE));
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 27a03b6..5f7a17d 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -54,10 +54,6 @@
         int action, in Bundle arguments, int interactionId,
         IAccessibilityInteractionConnectionCallback callback, long threadId);
 
-    boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId,
-        int interactionId, IAccessibilityInteractionConnectionCallback callback,
-        long threadId);
-
     AccessibilityWindowInfo getWindow(int windowId);
 
     List<AccessibilityWindowInfo> getWindows();
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java
index 2c7d502..26a61ae 100644
--- a/core/java/android/alsa/AlsaCardsParser.java
+++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -80,8 +80,11 @@
               } else if (lineIndex == 1) {
                   tokenIndex = mTokenizer.nextToken(line, 0);
                   if (tokenIndex != -1) {
-                      mCardDescription = line.substring(tokenIndex);
-                      mIsUsb = mCardDescription.contains(kUsbCardKeyStr);
+                      int keyIndex = line.indexOf(kUsbCardKeyStr);
+                      mIsUsb = keyIndex != -1;
+                      if (mIsUsb) {
+                          mCardDescription = line.substring(tokenIndex, keyIndex - 1);
+                      }
                   }
             }
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a09bca1..8b4b292 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1534,13 +1534,17 @@
      * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
      * application.  You can override this method to place into the bundle anything
      * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
-     * of the assist Intent.  The default implementation does nothing.
+     * of the assist Intent.  The default implementation automatically generates a
+     * {@link AssistData} from your activity and places it in to the Bundle; if you
+     * don't want your UI reported to the assistant, don't call this default
+     * implementation.
      *
      * <p>This function will be called after any global assist callbacks that had
      * been registered with {@link Application#registerOnProvideAssistDataListener
      * Application.registerOnProvideAssistDataListener}.
      */
     public void onProvideAssistData(Bundle data) {
+        data.putParcelable(AssistData.ASSIST_KEY, new AssistData(this));
     }
 
     /**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7a636db..c6ffef6 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -256,6 +256,9 @@
     /** @hide User operation call: given user id is the current user, can't be stopped. */
     public static final int USER_OP_IS_CURRENT = -2;
 
+    /** @hide Process does not exist. */
+    public static final int PROCESS_STATE_NONEXISTENT = -1;
+
     /** @hide Process is a persistent system process. */
     public static final int PROCESS_STATE_PERSISTENT = 0;
 
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 379fe11..47f57ea 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -766,6 +766,14 @@
             return true;
         }
 
+        case GET_FOCUSED_STACK_ID_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int focusedStackId = getFocusedStackId();
+            reply.writeNoException();
+            reply.writeInt(focusedStackId);
+            return true;
+        }
+
         case REGISTER_TASK_STACK_LISTENER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -2292,6 +2300,15 @@
             return true;
         }
 
+        case SET_TASK_RESIZEABLE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int taskId = data.readInt();
+            boolean resizeable = (data.readInt() == 1) ? true : false;
+            setTaskResizeable(taskId, resizeable);
+            reply.writeNoException();
+            return true;
+        }
+
         case GET_TASK_DESCRIPTION_ICON_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String filename = data.readString();
@@ -3290,6 +3307,18 @@
         reply.recycle();
     }
     @Override
+    public int getFocusedStackId() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(GET_FOCUSED_STACK_ID_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int focusedStackId = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return focusedStackId;
+    }
+    @Override
     public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -5382,6 +5411,19 @@
     }
 
     @Override
+    public void setTaskResizeable(int taskId, boolean resizeable) throws  RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(taskId);
+        data.writeInt(resizeable ? 1 : 0);
+        mRemote.transact(SET_TASK_RESIZEABLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    @Override
     public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/AssistData.java b/core/java/android/app/AssistData.java
new file mode 100644
index 0000000..8d3d348
--- /dev/null
+++ b/core/java/android/app/AssistData.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewAssistData;
+import android.view.ViewGroup;
+import android.view.ViewRootImpl;
+import android.view.WindowManagerGlobal;
+import android.widget.Checkable;
+
+import java.util.ArrayList;
+
+/**
+ * Assist data automatically created by the platform's implementation
+ * of {@link Activity#onProvideAssistData}.  Retrieve it from the assist
+ * data with {@link #getAssistData(android.os.Bundle)}.
+ */
+final public class AssistData implements Parcelable {
+    static final String TAG = "AssistData";
+
+    /**
+     * Key name this data structure is stored in the Bundle generated by
+     * {@link Activity#onProvideAssistData}.
+     */
+    public static final String ASSIST_KEY = "android:assist";
+
+    final ArrayList<ViewNodeImpl> mRootViews = new ArrayList<>();
+
+    ViewAssistDataImpl mTmpViewAssistDataImpl = new ViewAssistDataImpl();
+    Bundle mTmpExtras = new Bundle();
+
+    final static class ViewAssistDataImpl extends ViewAssistData {
+        CharSequence mText;
+        int mTextSelectionStart = -1;
+        int mTextSelectionEnd = -1;
+        CharSequence mHint;
+
+        @Override
+        public void setText(CharSequence text) {
+            mText = text;
+            mTextSelectionStart = mTextSelectionEnd = -1;
+        }
+
+        @Override
+        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
+            mText = text;
+            mTextSelectionStart = selectionStart;
+            mTextSelectionEnd = selectionEnd;
+        }
+
+        @Override
+        public void setHint(CharSequence hint) {
+            mHint = hint;
+        }
+
+        @Override
+        public CharSequence getText() {
+            return mText;
+        }
+
+        @Override
+        public int getTextSelectionStart() {
+            return mTextSelectionStart;
+        }
+
+        @Override
+        public int getTextSelectionEnd() {
+            return mTextSelectionEnd;
+        }
+
+        @Override
+        public CharSequence getHint() {
+            return mHint;
+        }
+    }
+
+    final static class ViewNodeTextImpl {
+        final String mText;
+        final int mTextSelectionStart;
+        final int mTextSelectionEnd;
+        final String mHint;
+
+        ViewNodeTextImpl(ViewAssistDataImpl data) {
+            mText = data.mText != null ? data.mText.toString() : null;
+            mTextSelectionStart = data.mTextSelectionStart;
+            mTextSelectionEnd = data.mTextSelectionEnd;
+            mHint = data.mHint != null ? data.mHint.toString() : null;
+        }
+
+        ViewNodeTextImpl(Parcel in) {
+            mText = in.readString();
+            mTextSelectionStart = in.readInt();
+            mTextSelectionEnd = in.readInt();
+            mHint = in.readString();
+        }
+
+        void writeToParcel(Parcel out) {
+            out.writeString(mText);
+            out.writeInt(mTextSelectionStart);
+            out.writeInt(mTextSelectionEnd);
+            out.writeString(mHint);
+        }
+    }
+
+    final static class ViewNodeImpl {
+        final int mX;
+        final int mY;
+        final int mScrollX;
+        final int mScrollY;
+        final int mWidth;
+        final int mHeight;
+
+        static final int FLAGS_DISABLED = 0x00000001;
+        static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
+        static final int FLAGS_FOCUSABLE = 0x00000010;
+        static final int FLAGS_FOCUSED = 0x00000020;
+        static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000;
+        static final int FLAGS_SELECTED = 0x00000040;
+        static final int FLAGS_ACTIVATED = 0x40000000;
+        static final int FLAGS_CHECKABLE = 0x00000100;
+        static final int FLAGS_CHECKED = 0x00000200;
+        static final int FLAGS_CLICKABLE = 0x00004000;
+        static final int FLAGS_LONG_CLICKABLE = 0x00200000;
+
+        final int mFlags;
+
+        final String mClassName;
+        final String mContentDescription;
+
+        final ViewNodeTextImpl mText;
+        final Bundle mExtras;
+
+        final ViewNodeImpl[] mChildren;
+
+        ViewNodeImpl(AssistData assistData, View view, int left, int top,
+                CharSequence contentDescription) {
+            mX = left;
+            mY = top;
+            mScrollX = view.getScrollX();
+            mScrollY = view.getScrollY();
+            mWidth = view.getWidth();
+            mHeight = view.getHeight();
+            int flags = view.getVisibility();
+            if (!view.isEnabled()) {
+                flags |= FLAGS_DISABLED;
+            }
+            if (!view.isClickable()) {
+                flags |= FLAGS_CLICKABLE;
+            }
+            if (!view.isFocusable()) {
+                flags |= FLAGS_FOCUSABLE;
+            }
+            if (!view.isFocused()) {
+                flags |= FLAGS_FOCUSED;
+            }
+            if (!view.isAccessibilityFocused()) {
+                flags |= FLAGS_ACCESSIBILITY_FOCUSED;
+            }
+            if (!view.isSelected()) {
+                flags |= FLAGS_SELECTED;
+            }
+            if (!view.isActivated()) {
+                flags |= FLAGS_ACTIVATED;
+            }
+            if (!view.isLongClickable()) {
+                flags |= FLAGS_LONG_CLICKABLE;
+            }
+            if (view instanceof Checkable) {
+                flags |= FLAGS_CHECKABLE;
+                if (((Checkable)view).isChecked()) {
+                    flags |= FLAGS_CHECKED;
+                }
+            }
+            mFlags = flags;
+            mClassName = view.getAccessibilityClassName().toString();
+            mContentDescription = contentDescription != null ? contentDescription.toString() : null;
+            final ViewAssistDataImpl viewData = assistData.mTmpViewAssistDataImpl;
+            final Bundle extras = assistData.mTmpExtras;
+            view.onProvideAssistData(viewData, extras);
+            if (viewData.mText != null || viewData.mHint != null) {
+                mText = new ViewNodeTextImpl(viewData);
+                assistData.mTmpViewAssistDataImpl = new ViewAssistDataImpl();
+            } else {
+                mText = null;
+            }
+            if (!extras.isEmpty()) {
+                mExtras = extras;
+                assistData.mTmpExtras = new Bundle();
+            } else {
+                mExtras = null;
+            }
+            if (view instanceof ViewGroup) {
+                ViewGroup vg = (ViewGroup)view;
+                final int NCHILDREN = vg.getChildCount();
+                if (NCHILDREN > 0) {
+                    mChildren = new ViewNodeImpl[NCHILDREN];
+                    for (int i=0; i<NCHILDREN; i++) {
+                        mChildren[i] = new ViewNodeImpl(assistData, vg.getChildAt(i));
+                    }
+                } else {
+                    mChildren = null;
+                }
+            } else {
+                mChildren = null;
+            }
+        }
+
+        ViewNodeImpl(AssistData assistData, View view) {
+            this(assistData, view, view.getLeft(), view.getTop(), view.getContentDescription());
+        }
+
+        ViewNodeImpl(Parcel in) {
+            mX = in.readInt();
+            mY = in.readInt();
+            mScrollX = in.readInt();
+            mScrollY = in.readInt();
+            mWidth = in.readInt();
+            mHeight = in.readInt();
+            mFlags = in.readInt();
+            mClassName = in.readString();
+            mContentDescription = in.readString();
+            if (in.readInt() != 0) {
+                mText = new ViewNodeTextImpl(in);
+            } else {
+                mText = null;
+            }
+            mExtras = in.readBundle();
+            final int NCHILDREN = in.readInt();
+            if (NCHILDREN > 0) {
+                mChildren = new ViewNodeImpl[NCHILDREN];
+                for (int i=0; i<NCHILDREN; i++) {
+                    mChildren[i] = new ViewNodeImpl(in);
+                }
+            } else {
+                mChildren = null;
+            }
+        }
+
+        void writeToParcel(Parcel out) {
+            out.writeInt(mX);
+            out.writeInt(mY);
+            out.writeInt(mScrollX);
+            out.writeInt(mScrollY);
+            out.writeInt(mWidth);
+            out.writeInt(mHeight);
+            out.writeInt(mFlags);
+            out.writeString(mClassName);
+            out.writeString(mContentDescription);
+            if (mText != null) {
+                out.writeInt(1);
+                mText.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+            }
+            out.writeBundle(mExtras);
+            if (mChildren != null) {
+                final int NCHILDREN = mChildren.length;
+                out.writeInt(NCHILDREN);
+                for (int i=0; i<NCHILDREN; i++) {
+                    mChildren[i].writeToParcel(out);
+                }
+            } else {
+                out.writeInt(0);
+            }
+        }
+    }
+
+    /**
+     * Provides access to information about a single view in the assist data.
+     */
+    static public class ViewNode {
+        ViewNodeImpl mImpl;
+
+        public ViewNode() {
+        }
+
+        public int getLeft() {
+            return mImpl.mX;
+        }
+
+        public int getTop() {
+            return mImpl.mY;
+        }
+
+        public int getScrollX() {
+            return mImpl.mScrollX;
+        }
+
+        public int getScrollY() {
+            return mImpl.mScrollY;
+        }
+
+        public int getWidth() {
+            return mImpl.mWidth;
+        }
+
+        public int getHeight() {
+            return mImpl.mHeight;
+        }
+
+        public int getVisibility() {
+            return mImpl.mFlags&ViewNodeImpl.FLAGS_VISIBILITY_MASK;
+        }
+
+        public boolean isEnabled() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_DISABLED) == 0;
+        }
+
+        public boolean isClickable() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_CLICKABLE) != 0;
+        }
+
+        public boolean isFocusable() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_FOCUSABLE) != 0;
+        }
+
+        public boolean isFocused() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_FOCUSED) != 0;
+        }
+
+        public boolean isAccessibilityFocused() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
+        }
+
+        public boolean isCheckable() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_CHECKABLE) != 0;
+        }
+
+        public boolean isChecked() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_CHECKED) != 0;
+        }
+
+        public boolean isSelected() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_SELECTED) != 0;
+        }
+
+        public boolean isActivated() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_ACTIVATED) != 0;
+        }
+
+        public boolean isLongClickable() {
+            return (mImpl.mFlags&ViewNodeImpl.FLAGS_LONG_CLICKABLE) != 0;
+        }
+
+        public String getClassName() {
+            return mImpl.mClassName;
+        }
+
+        public String getContentDescription() {
+            return mImpl.mContentDescription;
+        }
+
+        public String getText() {
+            return mImpl.mText != null ? mImpl.mText.mText : null;
+        }
+
+        public int getTextSelectionStart() {
+            return mImpl.mText != null ? mImpl.mText.mTextSelectionStart : -1;
+        }
+
+        public int getTextSelectionEnd() {
+            return mImpl.mText != null ? mImpl.mText.mTextSelectionEnd : -1;
+        }
+
+        public String getHint() {
+            return mImpl.mText != null ? mImpl.mText.mHint : null;
+        }
+
+        public Bundle getExtras() {
+            return mImpl.mExtras;
+        }
+
+        public int getChildCount() {
+            return mImpl.mChildren != null ? mImpl.mChildren.length : 0;
+        }
+
+        public void getChildAt(int index, ViewNode outNode) {
+            outNode.mImpl = mImpl.mChildren[index];
+        }
+    }
+
+    AssistData(Activity activity) {
+        ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
+                activity.getActivityToken());
+        for (int i=0; i<views.size(); i++) {
+            ViewRootImpl root = views.get(i);
+            View view = root.getView();
+            Rect rect = new Rect();
+            view.getBoundsOnScreen(rect);
+            CharSequence title = root.getTitle();
+            mRootViews.add(new ViewNodeImpl(this, view, rect.left, rect.top,
+                    title != null ? title : view.getContentDescription()));
+        }
+    }
+
+    AssistData(Parcel in) {
+        final int N = in.readInt();
+        for (int i=0; i<N; i++) {
+            mRootViews.add(new ViewNodeImpl(in));
+        }
+        //dump();
+    }
+
+    void dump() {
+        ViewNode node = new ViewNode();
+        final int N = getWindowCount();
+        for (int i=0; i<N; i++) {
+            Log.i(TAG, "Window #" + i + ":");
+            getWindowAt(i, node);
+            dump("  ", node);
+        }
+    }
+
+    void dump(String prefix, ViewNode node) {
+        Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop()
+                + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName());
+        int scrollX = node.getScrollX();
+        int scrollY = node.getScrollY();
+        if (scrollX != 0 || scrollY != 0) {
+            Log.i(TAG, prefix + "  Scroll: " + scrollX + "," + scrollY);
+        }
+        String contentDescription = node.getContentDescription();
+        if (contentDescription != null) {
+            Log.i(TAG, prefix + "  Content description: " + contentDescription);
+        }
+        String text = node.getText();
+        if (text != null) {
+            Log.i(TAG, prefix + " Text (sel " + node.getTextSelectionStart() + "-"
+                    + node.getTextSelectionEnd() + "): " + text);
+        }
+        String hint = node.getHint();
+        if (hint != null) {
+            Log.i(TAG, prefix + "  Hint: " + hint);
+        }
+        Bundle extras = node.getExtras();
+        if (extras != null) {
+            Log.i(TAG, prefix + "  Extras: " + extras);
+        }
+        final int NCHILDREN = node.getChildCount();
+        if (NCHILDREN > 0) {
+            Log.i(TAG, prefix + "  Children:");
+            String cprefix = prefix + "    ";
+            ViewNode cnode = new ViewNode();
+            for (int i=0; i<NCHILDREN; i++) {
+                node.getChildAt(i, cnode);
+                dump(cprefix, cnode);
+            }
+        }
+    }
+
+    /**
+     * Retrieve the framework-generated AssistData that is stored within
+     * the Bundle filled in by {@link Activity#onProvideAssistData}.
+     */
+    public static AssistData getAssistData(Bundle assistBundle) {
+        return assistBundle.getParcelable(ASSIST_KEY);
+    }
+
+    /**
+     * Return the number of window contents that have been collected in this assist data.
+     */
+    public int getWindowCount() {
+        return mRootViews.size();
+    }
+
+    /**
+     * Return the root view for one of the windows in the assist data.
+     * @param index Which window to retrieve, may be 0 to {@link #getWindowCount()}-1.
+     * @param outNode Node in which to place the window's root view.
+     */
+    public void getWindowAt(int index, ViewNode outNode) {
+        outNode.mImpl = mRootViews.get(index);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        int start = out.dataPosition();
+        final int N = mRootViews.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            mRootViews.get(i).writeToParcel(out);
+        }
+        Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes");
+    }
+
+    public static final Parcelable.Creator<AssistData> CREATOR
+            = new Parcelable.Creator<AssistData>() {
+        public AssistData createFromParcel(Parcel in) {
+            return new AssistData(in);
+        }
+
+        public AssistData[] newArray(int size) {
+            return new AssistData[size];
+        }
+    };
+}
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index 52884f7..ff1175f 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -32,6 +32,7 @@
     void checkEmbeddedAllowed(in Intent intent);
     void checkEmbeddedAllowedIntentSender(in IIntentSender intentSender);
     int getDisplayId();
+    int getStackId();
     boolean injectEvent(in InputEvent event);
     void release();
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index f152c6f..467c99a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -139,6 +139,7 @@
     public StackInfo getStackInfo(int stackId) throws RemoteException;
     public boolean isInHomeStack(int taskId) throws RemoteException;
     public void setFocusedStack(int stackId) throws RemoteException;
+    public int getFocusedStackId() throws RemoteException;
     public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException;
     public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
@@ -459,6 +460,7 @@
 
     public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
             throws RemoteException;
+    public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
     public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException;
 
     public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts)
@@ -800,4 +802,6 @@
     // Start of M transactions
     int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
     int CREATE_STACK_ON_DISPLAY = IBinder.FIRST_CALL_TRANSACTION+281;
+    int GET_FOCUSED_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+282;
+    int SET_TASK_RESIZEABLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+283;
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 860b9cc..87e744c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5065,6 +5065,403 @@
     }
 
     /**
+     * <p>Helper class to add Android Auto extensions to notifications. To create a notification
+     * with car extensions:
+     *
+     * <ol>
+     *  <li>Create an {@link Notification.Builder}, setting any desired
+     *  properties.
+     *  <li>Create a {@link CarExtender}.
+     *  <li>Set car-specific properties using the {@code add} and {@code set} methods of
+     *  {@link CarExtender}.
+     *  <li>Call {@link Notification.Builder#extend(Notification.Extender)}
+     *  to apply the extensions to a notification.
+     * </ol>
+     *
+     * <pre class="prettyprint">
+     * Notification notification = new Notification.Builder(context)
+     *         ...
+     *         .extend(new CarExtender()
+     *                 .set*(...))
+     *         .build();
+     * </pre>
+     *
+     * <p>Car extensions can be accessed on an existing notification by using the
+     * {@code CarExtender(Notification)} constructor, and then using the {@code get} methods
+     * to access values.
+     */
+    public static final class CarExtender implements Extender {
+        private static final String TAG = "CarExtender";
+
+        private static final String EXTRA_CAR_EXTENDER = "android.car.EXTENSIONS";
+        private static final String EXTRA_LARGE_ICON = "large_icon";
+        private static final String EXTRA_CONVERSATION = "car_conversation";
+        private static final String EXTRA_COLOR = "app_color";
+
+        private Bitmap mLargeIcon;
+        private UnreadConversation mUnreadConversation;
+        private int mColor = Notification.COLOR_DEFAULT;
+
+        /**
+         * Create a {@link CarExtender} with default options.
+         */
+        public CarExtender() {
+        }
+
+        /**
+         * Create a {@link CarExtender} from the CarExtender options of an existing Notification.
+         *
+         * @param notif The notification from which to copy options.
+         */
+        public CarExtender(Notification notif) {
+            Bundle carBundle = notif.extras == null ?
+                    null : notif.extras.getBundle(EXTRA_CAR_EXTENDER);
+            if (carBundle != null) {
+                mLargeIcon = carBundle.getParcelable(EXTRA_LARGE_ICON);
+                mColor = carBundle.getInt(EXTRA_COLOR, Notification.COLOR_DEFAULT);
+
+                Bundle b = carBundle.getBundle(EXTRA_CONVERSATION);
+                mUnreadConversation = UnreadConversation.getUnreadConversationFromBundle(b);
+            }
+        }
+
+        /**
+         * Apply car extensions to a notification that is being built. This is typically called by
+         * the {@link Notification.Builder#extend(Notification.Extender)}
+         * method of {@link Notification.Builder}.
+         */
+        @Override
+        public Notification.Builder extend(Notification.Builder builder) {
+            Bundle carExtensions = new Bundle();
+
+            if (mLargeIcon != null) {
+                carExtensions.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
+            }
+            if (mColor != Notification.COLOR_DEFAULT) {
+                carExtensions.putInt(EXTRA_COLOR, mColor);
+            }
+
+            if (mUnreadConversation != null) {
+                Bundle b = mUnreadConversation.getBundleForUnreadConversation();
+                carExtensions.putBundle(EXTRA_CONVERSATION, b);
+            }
+
+            builder.getExtras().putBundle(EXTRA_CAR_EXTENDER, carExtensions);
+            return builder;
+        }
+
+        /**
+         * Sets the accent color to use when Android Auto presents the notification.
+         *
+         * Android Auto uses the color set with {@link Notification.Builder#setColor(int)}
+         * to accent the displayed notification. However, not all colors are acceptable in an
+         * automotive setting. This method can be used to override the color provided in the
+         * notification in such a situation.
+         */
+        public CarExtender setColor(int color) {
+            mColor = color;
+            return this;
+        }
+
+        /**
+         * Gets the accent color.
+         *
+         * @see setColor
+         */
+        public int getColor() {
+            return mColor;
+        }
+
+        /**
+         * Sets the large icon of the car notification.
+         *
+         * If no large icon is set in the extender, Android Auto will display the icon
+         * specified by {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap)}
+         *
+         * @param largeIcon The large icon to use in the car notification.
+         * @return This object for method chaining.
+         */
+        public CarExtender setLargeIcon(Bitmap largeIcon) {
+            mLargeIcon = largeIcon;
+            return this;
+        }
+
+        /**
+         * Gets the large icon used in this car notification, or null if no icon has been set.
+         *
+         * @return The large icon for the car notification.
+         * @see CarExtender#setLargeIcon
+         */
+        public Bitmap getLargeIcon() {
+            return mLargeIcon;
+        }
+
+        /**
+         * Sets the unread conversation in a message notification.
+         *
+         * @param unreadConversation The unread part of the conversation this notification conveys.
+         * @return This object for method chaining.
+         */
+        public CarExtender setUnreadConversation(UnreadConversation unreadConversation) {
+            mUnreadConversation = unreadConversation;
+            return this;
+        }
+
+        /**
+         * Returns the unread conversation conveyed by this notification.
+         * @see #setUnreadConversation(UnreadConversation)
+         */
+        public UnreadConversation getUnreadConversation() {
+            return mUnreadConversation;
+        }
+
+        /**
+         * A class which holds the unread messages from a conversation.
+         */
+        public static class UnreadConversation {
+            private static final String KEY_AUTHOR = "author";
+            private static final String KEY_TEXT = "text";
+            private static final String KEY_MESSAGES = "messages";
+            private static final String KEY_REMOTE_INPUT = "remote_input";
+            private static final String KEY_ON_REPLY = "on_reply";
+            private static final String KEY_ON_READ = "on_read";
+            private static final String KEY_PARTICIPANTS = "participants";
+            private static final String KEY_TIMESTAMP = "timestamp";
+
+            private final String[] mMessages;
+            private final RemoteInput mRemoteInput;
+            private final PendingIntent mReplyPendingIntent;
+            private final PendingIntent mReadPendingIntent;
+            private final String[] mParticipants;
+            private final long mLatestTimestamp;
+
+            UnreadConversation(String[] messages, RemoteInput remoteInput,
+                    PendingIntent replyPendingIntent, PendingIntent readPendingIntent,
+                    String[] participants, long latestTimestamp) {
+                mMessages = messages;
+                mRemoteInput = remoteInput;
+                mReadPendingIntent = readPendingIntent;
+                mReplyPendingIntent = replyPendingIntent;
+                mParticipants = participants;
+                mLatestTimestamp = latestTimestamp;
+            }
+
+            /**
+             * Gets the list of messages conveyed by this notification.
+             */
+            public String[] getMessages() {
+                return mMessages;
+            }
+
+            /**
+             * Gets the remote input that will be used to convey the response to a message list, or
+             * null if no such remote input exists.
+             */
+            public RemoteInput getRemoteInput() {
+                return mRemoteInput;
+            }
+
+            /**
+             * Gets the pending intent that will be triggered when the user replies to this
+             * notification.
+             */
+            public PendingIntent getReplyPendingIntent() {
+                return mReplyPendingIntent;
+            }
+
+            /**
+             * Gets the pending intent that Android Auto will send after it reads aloud all messages
+             * in this object's message list.
+             */
+            public PendingIntent getReadPendingIntent() {
+                return mReadPendingIntent;
+            }
+
+            /**
+             * Gets the participants in the conversation.
+             */
+            public String[] getParticipants() {
+                return mParticipants;
+            }
+
+            /**
+             * Gets the firs participant in the conversation.
+             */
+            public String getParticipant() {
+                return mParticipants.length > 0 ? mParticipants[0] : null;
+            }
+
+            /**
+             * Gets the timestamp of the conversation.
+             */
+            public long getLatestTimestamp() {
+                return mLatestTimestamp;
+            }
+
+            Bundle getBundleForUnreadConversation() {
+                Bundle b = new Bundle();
+                String author = null;
+                if (mParticipants != null && mParticipants.length > 1) {
+                    author = mParticipants[0];
+                }
+                Parcelable[] messages = new Parcelable[mMessages.length];
+                for (int i = 0; i < messages.length; i++) {
+                    Bundle m = new Bundle();
+                    m.putString(KEY_TEXT, mMessages[i]);
+                    m.putString(KEY_AUTHOR, author);
+                    messages[i] = m;
+                }
+                b.putParcelableArray(KEY_MESSAGES, messages);
+                if (mRemoteInput != null) {
+                    b.putParcelable(KEY_REMOTE_INPUT, mRemoteInput);
+                }
+                b.putParcelable(KEY_ON_REPLY, mReplyPendingIntent);
+                b.putParcelable(KEY_ON_READ, mReadPendingIntent);
+                b.putStringArray(KEY_PARTICIPANTS, mParticipants);
+                b.putLong(KEY_TIMESTAMP, mLatestTimestamp);
+                return b;
+            }
+
+            static UnreadConversation getUnreadConversationFromBundle(Bundle b) {
+                if (b == null) {
+                    return null;
+                }
+                Parcelable[] parcelableMessages = b.getParcelableArray(KEY_MESSAGES);
+                String[] messages = null;
+                if (parcelableMessages != null) {
+                    String[] tmp = new String[parcelableMessages.length];
+                    boolean success = true;
+                    for (int i = 0; i < tmp.length; i++) {
+                        if (!(parcelableMessages[i] instanceof Bundle)) {
+                            success = false;
+                            break;
+                        }
+                        tmp[i] = ((Bundle) parcelableMessages[i]).getString(KEY_TEXT);
+                        if (tmp[i] == null) {
+                            success = false;
+                            break;
+                        }
+                    }
+                    if (success) {
+                        messages = tmp;
+                    } else {
+                        return null;
+                    }
+                }
+
+                PendingIntent onRead = b.getParcelable(KEY_ON_READ);
+                PendingIntent onReply = b.getParcelable(KEY_ON_REPLY);
+
+                RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT);
+
+                String[] participants = b.getStringArray(KEY_PARTICIPANTS);
+                if (participants == null || participants.length != 1) {
+                    return null;
+                }
+
+                return new UnreadConversation(messages,
+                        remoteInput,
+                        onReply,
+                        onRead,
+                        participants, b.getLong(KEY_TIMESTAMP));
+            }
+        };
+
+        /**
+         * Builder class for {@link CarExtender.UnreadConversation} objects.
+         */
+        public static class Builder {
+            private final List<String> mMessages = new ArrayList<String>();
+            private final String mParticipant;
+            private RemoteInput mRemoteInput;
+            private PendingIntent mReadPendingIntent;
+            private PendingIntent mReplyPendingIntent;
+            private long mLatestTimestamp;
+
+            /**
+             * Constructs a new builder for {@link CarExtender.UnreadConversation}.
+             *
+             * @param name The name of the other participant in the conversation.
+             */
+            public Builder(String name) {
+                mParticipant = name;
+            }
+
+            /**
+             * Appends a new unread message to the list of messages for this conversation.
+             *
+             * The messages should be added from oldest to newest.
+             *
+             * @param message The text of the new unread message.
+             * @return This object for method chaining.
+             */
+            public Builder addMessage(String message) {
+                mMessages.add(message);
+                return this;
+            }
+
+            /**
+             * Sets the pending intent and remote input which will convey the reply to this
+             * notification.
+             *
+             * @param pendingIntent The pending intent which will be triggered on a reply.
+             * @param remoteInput The remote input parcelable which will carry the reply.
+             * @return This object for method chaining.
+             *
+             * @see CarExtender.UnreadConversation#getRemoteInput
+             * @see CarExtender.UnreadConversation#getReplyPendingIntent
+             */
+            public Builder setReplyAction(
+                    PendingIntent pendingIntent, RemoteInput remoteInput) {
+                mRemoteInput = remoteInput;
+                mReplyPendingIntent = pendingIntent;
+
+                return this;
+            }
+
+            /**
+             * Sets the pending intent that will be sent once the messages in this notification
+             * are read.
+             *
+             * @param pendingIntent The pending intent to use.
+             * @return This object for method chaining.
+             */
+            public Builder setReadPendingIntent(PendingIntent pendingIntent) {
+                mReadPendingIntent = pendingIntent;
+                return this;
+            }
+
+            /**
+             * Sets the timestamp of the most recent message in an unread conversation.
+             *
+             * If a messaging notification has been posted by your application and has not
+             * yet been cancelled, posting a later notification with the same id and tag
+             * but without a newer timestamp may result in Android Auto not displaying a
+             * heads up notification for the later notification.
+             *
+             * @param timestamp The timestamp of the most recent message in the conversation.
+             * @return This object for method chaining.
+             */
+            public Builder setLatestTimestamp(long timestamp) {
+                mLatestTimestamp = timestamp;
+                return this;
+            }
+
+            /**
+             * Builds a new unread conversation object.
+             *
+             * @return The new unread conversation object.
+             */
+            public UnreadConversation build() {
+                String[] messages = mMessages.toArray(new String[mMessages.size()]);
+                String[] participants = { mParticipant };
+                return new UnreadConversation(messages, mRemoteInput, mReplyPendingIntent,
+                        mReadPendingIntent, participants, mLatestTimestamp);
+            }
+        }
+    }
+
+    /**
      * Get an array of Notification objects from a parcelable array bundle field.
      * Update the bundle to have a typed array so fetches in the future don't need
      * to do an array copy.
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 4427ce1..e617553 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.Nullable;
 import android.content.SharedPreferences;
 import android.os.FileUtils;
 import android.os.Looper;
@@ -217,7 +218,8 @@
         }
     }
 
-    public String getString(String key, String defValue) {
+    @Nullable
+    public String getString(String key, @Nullable String defValue) {
         synchronized (this) {
             awaitLoadedLocked();
             String v = (String)mMap.get(key);
@@ -225,7 +227,8 @@
         }
     }
 
-    public Set<String> getStringSet(String key, Set<String> defValues) {
+    @Nullable
+    public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
         synchronized (this) {
             awaitLoadedLocked();
             Set<String> v = (Set<String>) mMap.get(key);
@@ -303,13 +306,13 @@
         private final Map<String, Object> mModified = Maps.newHashMap();
         private boolean mClear = false;
 
-        public Editor putString(String key, String value) {
+        public Editor putString(String key, @Nullable String value) {
             synchronized (this) {
                 mModified.put(key, value);
                 return this;
             }
         }
-        public Editor putStringSet(String key, Set<String> values) {
+        public Editor putStringSet(String key, @Nullable Set<String> values) {
             synchronized (this) {
                 mModified.put(key,
                         (values == null) ? null : new HashSet<String>(values));
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 8bfe6d3..90d84ee 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -994,6 +994,47 @@
     }
 
     /**
+     * Clear the wallpaper.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void clearWallpaper() {
+        if (sGlobals.mService == null) {
+            Log.w(TAG, "WallpaperService not running");
+            return;
+        }
+        try {
+            sGlobals.mService.clearWallpaper();
+        } catch (RemoteException e) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Set the live wallpaper.
+     *
+     * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
+     * permission.
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean setWallpaperComponent(ComponentName name) {
+        if (sGlobals.mService == null) {
+            Log.w(TAG, "WallpaperService not running");
+            return false;
+        }
+        try {
+            sGlobals.mService.setWallpaperComponent(name);
+            return true;
+        } catch (RemoteException e) {
+            // Ignore
+        }
+        return false;
+    }
+
+    /**
      * Set the position of the current wallpaper within any larger space, when
      * that wallpaper is visible behind the given window.  The X and Y offsets
      * are floating point numbers ranging from 0 to 1, representing where the
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 55c3960..af48909 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -332,6 +332,16 @@
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
 
     /**
+     * A boolean extra indicating whether device encryption is required as part of Device Owner
+     * provisioning.
+     *
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * provisioning via an NFC bump.
+     */
+    public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
+             "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
+
+    /**
      * This MIME type is used for starting the Device Owner provisioning.
      *
      * <p>During device owner provisioning a device admin app is set as the owner of the device.
@@ -361,7 +371,8 @@
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li>
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li></ul>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li></ul>
      *
      * <p> When device owner provisioning has completed, an intent of the type
      * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -694,7 +705,7 @@
     public void setPasswordQuality(ComponentName admin, int quality) {
         if (mService != null) {
             try {
-                mService.setPasswordQuality(admin, quality, UserHandle.myUserId());
+                mService.setPasswordQuality(admin, quality);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -747,7 +758,7 @@
     public void setPasswordMinimumLength(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumLength(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumLength(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -801,7 +812,7 @@
     public void setPasswordMinimumUpperCase(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumUpperCase(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumUpperCase(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -862,7 +873,7 @@
     public void setPasswordMinimumLowerCase(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumLowerCase(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumLowerCase(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -922,7 +933,7 @@
     public void setPasswordMinimumLetters(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumLetters(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumLetters(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -980,7 +991,7 @@
     public void setPasswordMinimumNumeric(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumNumeric(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumNumeric(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1039,7 +1050,7 @@
     public void setPasswordMinimumSymbols(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumSymbols(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumSymbols(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1097,7 +1108,7 @@
     public void setPasswordMinimumNonLetter(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordMinimumNonLetter(admin, length, UserHandle.myUserId());
+                mService.setPasswordMinimumNonLetter(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1157,7 +1168,7 @@
     public void setPasswordHistoryLength(ComponentName admin, int length) {
         if (mService != null) {
             try {
-                mService.setPasswordHistoryLength(admin, length, UserHandle.myUserId());
+                mService.setPasswordHistoryLength(admin, length);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1189,7 +1200,7 @@
     public void setPasswordExpirationTimeout(ComponentName admin, long timeout) {
         if (mService != null) {
             try {
-                mService.setPasswordExpirationTimeout(admin, timeout, UserHandle.myUserId());
+                mService.setPasswordExpirationTimeout(admin, timeout);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1334,7 +1345,7 @@
     public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) {
         if (mService != null) {
             try {
-                mService.setMaximumFailedPasswordsForWipe(admin, num, UserHandle.myUserId());
+                mService.setMaximumFailedPasswordsForWipe(admin, num);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1418,7 +1429,7 @@
     public boolean resetPassword(String password, int flags) {
         if (mService != null) {
             try {
-                return mService.resetPassword(password, flags, UserHandle.myUserId());
+                return mService.resetPassword(password, flags);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1442,7 +1453,7 @@
     public void setMaximumTimeToLock(ComponentName admin, long timeMs) {
         if (mService != null) {
             try {
-                mService.setMaximumTimeToLock(admin, timeMs, UserHandle.myUserId());
+                mService.setMaximumTimeToLock(admin, timeMs);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1592,7 +1603,7 @@
                             != android.net.Proxy.PROXY_VALID)
                         throw new IllegalArgumentException();
                 }
-                return mService.setGlobalProxy(admin, hostSpec, exclSpec, UserHandle.myUserId());
+                return mService.setGlobalProxy(admin, hostSpec, exclSpec);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1758,7 +1769,7 @@
     public int setStorageEncryption(ComponentName admin, boolean encrypt) {
         if (mService != null) {
             try {
-                return mService.setStorageEncryption(admin, encrypt, UserHandle.myUserId());
+                return mService.setStorageEncryption(admin, encrypt);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1977,7 +1988,7 @@
     public void setCameraDisabled(ComponentName admin, boolean disabled) {
         if (mService != null) {
             try {
-                mService.setCameraDisabled(admin, disabled, UserHandle.myUserId());
+                mService.setCameraDisabled(admin, disabled);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -2021,7 +2032,7 @@
     public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) {
         if (mService != null) {
             try {
-                mService.setScreenCaptureDisabled(admin, UserHandle.myUserId(), disabled);
+                mService.setScreenCaptureDisabled(admin, disabled);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -2065,7 +2076,7 @@
     public void setAutoTimeRequired(ComponentName admin, boolean required) {
         if (mService != null) {
             try {
-                mService.setAutoTimeRequired(admin, UserHandle.myUserId(), required);
+                mService.setAutoTimeRequired(admin, required);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -2106,7 +2117,7 @@
     public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
         if (mService != null) {
             try {
-                mService.setKeyguardDisabledFeatures(admin, which, UserHandle.myUserId());
+                mService.setKeyguardDisabledFeatures(admin, which);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -2688,8 +2699,7 @@
             PersistableBundle configuration) {
         if (mService != null) {
             try {
-                mService.setTrustAgentConfiguration(admin, target, configuration,
-                        UserHandle.myUserId());
+                mService.setTrustAgentConfiguration(admin, target, configuration);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -2918,9 +2928,9 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageNames List of input method package names.
-     * @return true if setting the restriction succeeded. It will fail if there is
-     *     one or more input method enabled, that are not in the list or user if the foreground
-     *     user.
+     * @return true if setting the restriction succeeded. It will fail if there are
+     *     one or more non-system input methods currently enabled that are not in
+     *     the packageNames list.
      */
     public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) {
         if (mService != null) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 0ca60c0..67bca4e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -32,34 +32,34 @@
  * {@hide}
  */
 interface IDevicePolicyManager {
-    void setPasswordQuality(in ComponentName who, int quality, int userHandle);
+    void setPasswordQuality(in ComponentName who, int quality);
     int getPasswordQuality(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumLength(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumLength(in ComponentName who, int length);
     int getPasswordMinimumLength(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumUpperCase(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumUpperCase(in ComponentName who, int length);
     int getPasswordMinimumUpperCase(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumLowerCase(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumLowerCase(in ComponentName who, int length);
     int getPasswordMinimumLowerCase(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumLetters(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumLetters(in ComponentName who, int length);
     int getPasswordMinimumLetters(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumNumeric(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumNumeric(in ComponentName who, int length);
     int getPasswordMinimumNumeric(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumSymbols(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumSymbols(in ComponentName who, int length);
     int getPasswordMinimumSymbols(in ComponentName who, int userHandle);
 
-    void setPasswordMinimumNonLetter(in ComponentName who, int length, int userHandle);
+    void setPasswordMinimumNonLetter(in ComponentName who, int length);
     int getPasswordMinimumNonLetter(in ComponentName who, int userHandle);
 
-    void setPasswordHistoryLength(in ComponentName who, int length, int userHandle);
+    void setPasswordHistoryLength(in ComponentName who, int length);
     int getPasswordHistoryLength(in ComponentName who, int userHandle);
 
-    void setPasswordExpirationTimeout(in ComponentName who, long expiration, int userHandle);
+    void setPasswordExpirationTimeout(in ComponentName who, long expiration);
     long getPasswordExpirationTimeout(in ComponentName who, int userHandle);
 
     long getPasswordExpiration(in ComponentName who, int userHandle);
@@ -68,33 +68,33 @@
     int getCurrentFailedPasswordAttempts(int userHandle);
     int getProfileWithMinimumFailedPasswordsForWipe(int userHandle);
 
-    void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, int userHandle);
+    void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num);
     int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle);
 
-    boolean resetPassword(String password, int flags, int userHandle);
+    boolean resetPassword(String password, int flags);
 
-    void setMaximumTimeToLock(in ComponentName who, long timeMs, int userHandle);
+    void setMaximumTimeToLock(in ComponentName who, long timeMs);
     long getMaximumTimeToLock(in ComponentName who, int userHandle);
 
     void lockNow();
 
     void wipeData(int flags, int userHandle);
 
-    ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList, int userHandle);
+    ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
     ComponentName getGlobalProxyAdmin(int userHandle);
     void setRecommendedGlobalProxy(in ComponentName admin, in ProxyInfo proxyInfo);
 
-    int setStorageEncryption(in ComponentName who, boolean encrypt, int userHandle);
+    int setStorageEncryption(in ComponentName who, boolean encrypt);
     boolean getStorageEncryption(in ComponentName who, int userHandle);
     int getStorageEncryptionStatus(int userHandle);
 
-    void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle);
+    void setCameraDisabled(in ComponentName who, boolean disabled);
     boolean getCameraDisabled(in ComponentName who, int userHandle);
 
-    void setScreenCaptureDisabled(in ComponentName who, int userHandle, boolean disabled);
+    void setScreenCaptureDisabled(in ComponentName who, boolean disabled);
     boolean getScreenCaptureDisabled(in ComponentName who, int userHandle);
 
-    void setKeyguardDisabledFeatures(in ComponentName who, int which, int userHandle);
+    void setKeyguardDisabledFeatures(in ComponentName who, int which);
     int getKeyguardDisabledFeatures(in ComponentName who, int userHandle);
 
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle);
@@ -186,7 +186,7 @@
     boolean getCrossProfileCallerIdDisabledForUser(int userId);
 
     void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
-            in PersistableBundle args, int userId);
+            in PersistableBundle args);
     List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
             in ComponentName agent, int userId);
 
@@ -194,7 +194,7 @@
     boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
     List<String> getCrossProfileWidgetProviders(in ComponentName admin);
 
-    void setAutoTimeRequired(in ComponentName who, int userHandle, boolean required);
+    void setAutoTimeRequired(in ComponentName who, boolean required);
     boolean getAutoTimeRequired();
 
     boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 0450150..767f59e 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.media.AudioManager;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -415,9 +416,16 @@
     }
 
     /**
-     * Tells remote device to adjust volume. Only if absolute volume is supported.
+     * Tells remote device to adjust volume. Only if absolute volume is
+     * supported. Uses the following values:
+     * <ul>
+     * <li>{@link AudioManager#ADJUST_LOWER}</li>
+     * <li>{@link AudioManager#ADJUST_RAISE}</li>
+     * <li>{@link AudioManager#ADJUST_MUTE}</li>
+     * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
+     * </ul>
      *
-     * @param direction 1 to increase volume, or -1 to decrease volume
+     * @param direction One of the supported adjust values.
      * @hide
      */
     public void adjustAvrcpAbsoluteVolume(int direction) {
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 46c9234..cd32dae 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -16,6 +16,8 @@
 
 package android.content;
 
+import android.annotation.Nullable;
+
 import java.util.Map;
 import java.util.Set;
 
@@ -78,7 +80,7 @@
          * @return Returns a reference to the same Editor object, so you can
          * chain put calls together.
          */
-        Editor putString(String key, String value);
+        Editor putString(String key, @Nullable String value);
         
         /**
          * Set a set of String values in the preferences editor, to be written
@@ -91,7 +93,7 @@
          * @return Returns a reference to the same Editor object, so you can
          * chain put calls together.
          */
-        Editor putStringSet(String key, Set<String> values);
+        Editor putStringSet(String key, @Nullable Set<String> values);
         
         /**
          * Set an int value in the preferences editor, to be written back once
@@ -254,7 +256,8 @@
      * 
      * @throws ClassCastException
      */
-    String getString(String key, String defValue);
+    @Nullable
+    String getString(String key, @Nullable String defValue);
     
     /**
      * Retrieve a set of String values from the preferences.
@@ -272,7 +275,8 @@
      * 
      * @throws ClassCastException
      */
-    Set<String> getStringSet(String key, Set<String> defValues);
+    @Nullable
+    Set<String> getStringSet(String key, @Nullable Set<String> defValues);
     
     /**
      * Retrieve an int value from the preferences.
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 641f843e..4723c0d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -641,6 +641,13 @@
      */
     public String parentActivityName;
 
+    /**
+     * Value indicating if the activity is resizeable to any dimension.
+     * See {@link android.R.attr#resizeableActivity}.
+     * @hide
+     */
+    public boolean resizeable;
+
     public ActivityInfo() {
     }
 
@@ -702,6 +709,7 @@
         if (uiOptions != 0) {
             pw.println(prefix + " uiOptions=0x" + Integer.toHexString(uiOptions));
         }
+        pw.println(prefix + "resizeable=" + resizeable);
         super.dumpBack(pw, prefix);
     }
     
@@ -730,6 +738,7 @@
         dest.writeString(parentActivityName);
         dest.writeInt(persistableMode);
         dest.writeInt(maxRecents);
+        dest.writeInt(resizeable ? 1 : 0);
     }
 
     public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -757,5 +766,6 @@
         parentActivityName = source.readString();
         persistableMode = source.readInt();
         maxRecents = source.readInt();
+        resizeable = (source.readInt() == 1);
     }
 }
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index ee23fcd..87b97aa 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -39,6 +39,7 @@
 
     private ActivityInfo mActivityInfo;
     private ComponentName mComponentName;
+    private ResolveInfo mResolveInfo;
     private UserHandle mUser;
     private long mFirstInstallTime;
 
@@ -52,6 +53,7 @@
     LauncherActivityInfo(Context context, ResolveInfo info, UserHandle user,
             long firstInstallTime) {
         this(context);
+        mResolveInfo = info;
         mActivityInfo = info.activityInfo;
         mComponentName = LauncherApps.getComponentName(info);
         mUser = user;
@@ -92,7 +94,7 @@
      * @return The label for the activity.
      */
     public CharSequence getLabel() {
-        return mActivityInfo.loadLabel(mPm);
+        return mResolveInfo.loadLabel(mPm);
     }
 
     /**
@@ -104,8 +106,22 @@
      * @return The drawable associated with the activity
      */
     public Drawable getIcon(int density) {
-        // TODO: Use density
-        return mActivityInfo.loadIcon(mPm);
+        int iconRes = mResolveInfo.getIconResource();
+        Resources resources = null;
+        Drawable icon = null;
+        // Get the preferred density icon from the app's resources
+        if (density != 0 && iconRes != 0) {
+            try {
+                resources = mPm.getResourcesForApplication(mActivityInfo.applicationInfo);
+                icon = resources.getDrawableForDensity(iconRes, density);
+            } catch (NameNotFoundException | Resources.NotFoundException exc) {
+            }
+        }
+        // Get the default density icon
+        if (icon == null) {
+            icon = mResolveInfo.loadIcon(mPm);
+        }
+        return icon;
     }
 
     /**
@@ -151,23 +167,7 @@
      * @return A badged icon for the activity.
      */
     public Drawable getBadgedIcon(int density) {
-        int iconRes = mActivityInfo.getIconResource();
-        Resources resources = null;
-        Drawable originalIcon = null;
-        try {
-            resources = mPm.getResourcesForApplication(mActivityInfo.applicationInfo);
-            try {
-                if (density != 0) {
-                    originalIcon = resources.getDrawableForDensity(iconRes, density);
-                }
-            } catch (Resources.NotFoundException e) {
-            }
-        } catch (NameNotFoundException nnfe) {
-        }
-
-        if (originalIcon == null) {
-            originalIcon = mActivityInfo.loadIcon(mPm);
-        }
+        Drawable originalIcon = getIcon(density);
 
         if (originalIcon instanceof BitmapDrawable) {
             return mPm.getUserBadgedIcon(originalIcon, mUser);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5c09b42..04777ba 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -49,6 +49,7 @@
 import android.util.Slog;
 import android.util.TypedValue;
 
+import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 
@@ -2759,9 +2760,17 @@
             }
         }
 
+        addSharedLibrariesForBackwardCompatibility(owner);
+
         return true;
     }
 
+    private static void addSharedLibrariesForBackwardCompatibility(Package owner) {
+        if (owner.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
+            owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, "org.apache.http.legacy");
+        }
+    }
+
     /**
      * Parse the {@code application} XML tree at the current parse location in a
      * <em>split APK</em> manifest.
@@ -2946,20 +2955,19 @@
             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
             boolean receiver, boolean hardwareAccelerated)
             throws XmlPullParserException, IOException {
-        TypedArray sa = res.obtainAttributes(attrs,
-                com.android.internal.R.styleable.AndroidManifestActivity);
+        TypedArray sa = res.obtainAttributes(attrs, R.styleable.AndroidManifestActivity);
 
         if (mParseActivityArgs == null) {
             mParseActivityArgs = new ParseComponentArgs(owner, outError,
-                    com.android.internal.R.styleable.AndroidManifestActivity_name,
-                    com.android.internal.R.styleable.AndroidManifestActivity_label,
-                    com.android.internal.R.styleable.AndroidManifestActivity_icon,
-                    com.android.internal.R.styleable.AndroidManifestActivity_logo,
-                    com.android.internal.R.styleable.AndroidManifestActivity_banner,
+                    R.styleable.AndroidManifestActivity_name,
+                    R.styleable.AndroidManifestActivity_label,
+                    R.styleable.AndroidManifestActivity_icon,
+                    R.styleable.AndroidManifestActivity_logo,
+                    R.styleable.AndroidManifestActivity_banner,
                     mSeparateProcesses,
-                    com.android.internal.R.styleable.AndroidManifestActivity_process,
-                    com.android.internal.R.styleable.AndroidManifestActivity_description,
-                    com.android.internal.R.styleable.AndroidManifestActivity_enabled);
+                    R.styleable.AndroidManifestActivity_process,
+                    R.styleable.AndroidManifestActivity_description,
+                    R.styleable.AndroidManifestActivity_enabled);
         }
         
         mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
@@ -2972,22 +2980,18 @@
             return null;
         }
 
-        boolean setExported = sa.hasValue(
-                com.android.internal.R.styleable.AndroidManifestActivity_exported);
+        boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
         if (setExported) {
-            a.info.exported = sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
+            a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
         }
 
-        a.info.theme = sa.getResourceId(
-                com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
+        a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
 
-        a.info.uiOptions = sa.getInt(
-                com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
+        a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
                 a.info.applicationInfo.uiOptions);
 
         String parentName = sa.getNonConfigurationString(
-                com.android.internal.R.styleable.AndroidManifestActivity_parentActivityName,
+                R.styleable.AndroidManifestActivity_parentActivityName,
                 Configuration.NATIVE_CONFIG_VERSION);
         if (parentName != null) {
             String parentClassName = buildClassName(a.info.packageName, parentName, outError);
@@ -3001,8 +3005,7 @@
         }
 
         String str;
-        str = sa.getNonConfigurationString(
-                com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
+        str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
         if (str == null) {
             a.info.permission = owner.applicationInfo.permission;
         } else {
@@ -3010,146 +3013,111 @@
         }
 
         str = sa.getNonConfigurationString(
-                com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity,
+                R.styleable.AndroidManifestActivity_taskAffinity,
                 Configuration.NATIVE_CONFIG_VERSION);
         a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
                 owner.applicationInfo.taskAffinity, str, outError);
 
         a.info.flags = 0;
         if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
-                false)) {
+                R.styleable.AndroidManifestActivity_multiprocess, false)) {
             a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
             a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
             a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
             a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
             a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
             a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
             a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
                 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
             a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
             a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_showOnLockScreen,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)) {
             a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_immersive,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
         }
 
-        if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
-                false)) {
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_primaryUserOnly, false)) {
             a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
         }
 
         if (!receiver) {
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
                     hardwareAccelerated)) {
                 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
             }
 
             a.info.launchMode = sa.getInt(
-                    com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
-                    ActivityInfo.LAUNCH_MULTIPLE);
+                    R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
             a.info.documentLaunchMode = sa.getInt(
-                    com.android.internal.R.styleable.AndroidManifestActivity_documentLaunchMode,
+                    R.styleable.AndroidManifestActivity_documentLaunchMode,
                     ActivityInfo.DOCUMENT_LAUNCH_NONE);
             a.info.maxRecents = sa.getInt(
-                    com.android.internal.R.styleable.AndroidManifestActivity_maxRecents,
+                    R.styleable.AndroidManifestActivity_maxRecents,
                     ActivityManager.getDefaultAppRecentsLimitStatic());
             a.info.screenOrientation = sa.getInt(
-                    com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
+                    R.styleable.AndroidManifestActivity_screenOrientation,
                     ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
-            a.info.configChanges = sa.getInt(
-                    com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
-                    0);
+            a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
             a.info.softInputMode = sa.getInt(
-                    com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
-                    0);
+                    R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
 
             a.info.persistableMode = sa.getInteger(
-                    com.android.internal.R.styleable.AndroidManifestActivity_persistableMode,
+                    R.styleable.AndroidManifestActivity_persistableMode,
                     ActivityInfo.PERSIST_ROOT_ONLY);
 
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_allowEmbedded,
-                    false)) {
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
                 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
             }
 
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_autoRemoveFromRecents,
-                    false)) {
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
                 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
             }
 
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_relinquishTaskIdentity,
-                    false)) {
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
                 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
             }
 
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_resumeWhilePausing,
-                    false)) {
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
                 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
             }
+
+            a.info.resizeable = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_resizeableActivity,
+                    owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.MNC);
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
-        }
 
-        if (receiver) {
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
-                    false)) {
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
                 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
                 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
                     Slog.w(TAG, "Activity exported request ignored due to singleUser: "
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index eace1c4..bb45b91 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -391,10 +391,12 @@
      * {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation}, in counts of {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep},
      * that are supported by this camera device.</p>
      * <p><b>Range of valid values:</b><br></p>
+     * <p>Range [0,0] indicates that exposure compensation is not supported.</p>
+     * <p>For LIMITED and FULL devices, range must follow below requirements if exposure
+     * compensation is supported (<code>range != [0, 0]</code>):</p>
      * <p><code>Min.exposure compensation * {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep} &lt;= -2 EV</code></p>
      * <p><code>Max.exposure compensation * {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep} &gt;= 2 EV</code></p>
-     * <p>LEGACY devices may support a smaller range than this, including the range [0,0], which
-     * indicates that changing the exposure compensation is not supported.</p>
+     * <p>LEGACY devices may support a smaller range than this.</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP
@@ -422,6 +424,17 @@
             new Key<Rational>("android.control.aeCompensationStep", Rational.class);
 
     /**
+     * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</p>
+     * <p>LIMITED or FULL devices will always list <code>true</code></p>
+     * <p>This key is available on all devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_LOCK
+     */
+    @PublicKey
+    public static final Key<Boolean> CONTROL_AE_LOCK_AVAILABLE =
+            new Key<Boolean>("android.control.aeLockAvailable", boolean.class);
+
+    /**
      * <p>List of auto-focus (AF) modes for {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} that are
      * supported by this camera device.</p>
      * <p>Not all the auto-focus modes may be supported by a
@@ -469,6 +482,22 @@
             new Key<int[]>("android.control.availableEffects", int[].class);
 
     /**
+     * <p>List of control modes for {@link CaptureRequest#CONTROL_MODE android.control.mode} that are supported by this camera
+     * device.</p>
+     * <p>This list contains control modes that can be set for the camera device.
+     * LEGACY mode devices will always support AUTO mode. LIMITED and FULL
+     * devices will always support OFF, AUTO modes.</p>
+     * <p><b>Range of valid values:</b><br>
+     * Any value listed in {@link CaptureRequest#CONTROL_MODE android.control.mode}</p>
+     * <p>This key is available on all devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_MODE
+     */
+    @PublicKey
+    public static final Key<int[]> CONTROL_AVAILABLE_MODES =
+            new Key<int[]>("android.control.availableModes", int[].class);
+
+    /**
      * <p>List of scene modes for {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} that are supported by this camera
      * device.</p>
      * <p>This list contains scene modes that can be set for the camera device.
@@ -530,6 +559,17 @@
             new Key<int[]>("android.control.awbAvailableModes", int[].class);
 
     /**
+     * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</p>
+     * <p>LIMITED or FULL devices will always list <code>true</code></p>
+     * <p>This key is available on all devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_AWB_LOCK
+     */
+    @PublicKey
+    public static final Key<Boolean> CONTROL_AWB_LOCK_AVAILABLE =
+            new Key<Boolean>("android.control.awbLockAvailable", boolean.class);
+
+    /**
      * <p>List of the maximum number of regions that can be used for metering in
      * auto-exposure (AE), auto-white balance (AWB), and auto-focus (AF);
      * this corresponds to the the maximum number of elements in
@@ -1069,8 +1109,11 @@
      * android.scaler.availableInputOutputFormatsMap. When using an
      * input stream, there must be at least one output stream
      * configured to to receive the reprocessed images.</p>
+     * <p>When an input stream and some output streams are used in a reprocessing request,
+     * only the input buffer will be used to produce these output stream buffers, and a
+     * new sensor image will not be captured.</p>
      * <p>For example, for Zero Shutter Lag (ZSL) still capture use case, the input
-     * stream image format will be RAW_OPAQUE, the associated output stream image format
+     * stream image format will be OPAQUE, the associated output stream image format
      * should be JPEG.</p>
      * <p><b>Range of valid values:</b><br></p>
      * <p>0 or 1.</p>
@@ -1080,8 +1123,8 @@
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
-     * @hide
      */
+    @PublicKey
     public static final Key<Integer> REQUEST_MAX_NUM_INPUT_STREAMS =
             new Key<Integer>("android.request.maxNumInputStreams", int.class);
 
@@ -1157,8 +1200,10 @@
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING MANUAL_POST_PROCESSING}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}</li>
+     *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING OPAQUE_REPROCESSING}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS READ_SENSOR_SETTINGS}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li>
+     *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
      * </ul></p>
      * <p>This key is available on all devices.</p>
      *
@@ -1167,8 +1212,10 @@
      * @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
      * @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
      * @see #REQUEST_AVAILABLE_CAPABILITIES_RAW
+     * @see #REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING
      * @see #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS
      * @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
+     * @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
      */
     @PublicKey
     public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
@@ -1345,10 +1392,10 @@
      * <p>The mapping of image formats that are supported by this
      * camera device for input streams, to their corresponding output formats.</p>
      * <p>All camera devices with at least 1
-     * android.request.maxNumInputStreams will have at least one
+     * {@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} will have at least one
      * available input format.</p>
      * <p>The camera device will support the following map of formats,
-     * if its dependent capability is supported:</p>
+     * if its dependent capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}) is supported:</p>
      * <table>
      * <thead>
      * <tr>
@@ -1359,45 +1406,42 @@
      * </thead>
      * <tbody>
      * <tr>
-     * <td align="left">RAW_OPAQUE</td>
+     * <td align="left">OPAQUE</td>
      * <td align="left">JPEG</td>
-     * <td align="left">ZSL</td>
+     * <td align="left">OPAQUE_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">RAW_OPAQUE</td>
+     * <td align="left">OPAQUE</td>
      * <td align="left">YUV_420_888</td>
-     * <td align="left">ZSL</td>
+     * <td align="left">OPAQUE_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">RAW_OPAQUE</td>
-     * <td align="left">RAW16</td>
-     * <td align="left">RAW</td>
-     * </tr>
-     * <tr>
-     * <td align="left">RAW16</td>
      * <td align="left">YUV_420_888</td>
-     * <td align="left">RAW</td>
-     * </tr>
-     * <tr>
-     * <td align="left">RAW16</td>
      * <td align="left">JPEG</td>
-     * <td align="left">RAW</td>
+     * <td align="left">YUV_REPROCESSING</td>
+     * </tr>
+     * <tr>
+     * <td align="left">YUV_420_888</td>
+     * <td align="left">YUV_420_888</td>
+     * <td align="left">YUV_REPROCESSING</td>
      * </tr>
      * </tbody>
      * </table>
-     * <p>For ZSL-capable camera devices, using the RAW_OPAQUE format
+     * <p>OPAQUE refers to a device-internal format that is not directly application-visible.
+     * An OPAQUE input or output surface can be acquired by
+     * OpaqueImageRingBufferQueue#getInputSurface() or
+     * OpaqueImageRingBufferQueue#getOutputSurface().
+     * For a OPAQUE_REPROCESSING-capable camera device, using the OPAQUE format
      * as either input or output will never hurt maximum frame rate (i.e.
-     * StreamConfigurationMap#getOutputStallDuration(int,Size)
-     * for a <code>format =</code> RAW_OPAQUE is always 0).</p>
+     * StreamConfigurationMap#getOutputStallDuration(klass,Size) is always 0),
+     * where klass is android.media.OpaqueImageRingBufferQueue.class.</p>
      * <p>Attempting to configure an input stream with output streams not
      * listed as available in this map is not valid.</p>
      * <p>TODO: typedef to ReprocessFormatMap</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
-     * <p><b>Full capability</b> -
-     * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
-     * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
-     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
      * @hide
      */
     public static final Key<int[]> SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP =
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index f6df302..af7d365 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -439,23 +439,40 @@
     public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3;
 
     /**
-     * <p>The camera device supports the Zero Shutter Lag use case.</p>
+     * <p>The camera device supports the Zero Shutter Lag reprocessing use case.</p>
      * <ul>
-     * <li>At least one input stream can be used.</li>
-     * <li>RAW_OPAQUE is supported as an output/input format</li>
-     * <li>Using RAW_OPAQUE does not cause a frame rate drop
+     * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
+     * <li>OPAQUE is supported as an output/input format, that is,
+     *   StreamConfigurationMap#getOutputSizes(klass) and
+     *   StreamConfigurationMap#getInputSizes(klass) return non empty Size[] and have common
+     *   sizes, where klass is android.media.OpaqueImageRingBufferQueue.class. See
+     *   android.scaler.availableInputOutputFormatsMap for detailed information about
+     *   OPAQUE format.</li>
+     * <li>android.scaler.availableInputOutputFormatsMap has the required map entries.</li>
+     * <li>Using OPAQUE does not cause a frame rate drop
      *   relative to the sensor's maximum capture rate (at that
-     *   resolution).</li>
-     * <li>RAW_OPAQUE will be reprocessable into both YUV_420_888
+     *   resolution), see android.scaler.availableInputOutputFormatsMap for more details.</li>
+     * <li>OPAQUE will be reprocessable into both YUV_420_888
      *   and JPEG formats.</li>
-     * <li>The maximum available resolution for RAW_OPAQUE streams
+     * <li>The maximum available resolution for OPAQUE streams
      *   (both input/output) will match the maximum available
      *   resolution of JPEG streams.</li>
+     * <li>Only below controls are effective for reprocessing requests and
+     *   will be present in capture results, other controls in reprocess
+     *   requests will be ignored by the camera device.<ul>
+     * <li>android.jpeg.*</li>
+     * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
+     * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
      * </ul>
+     * </li>
+     * </ul>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
-     * @hide
      */
-    public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4;
+    public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4;
 
     /**
      * <p>The camera device supports accurately reporting the sensor settings for many of
@@ -515,6 +532,45 @@
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6;
 
+    /**
+     * <p>The camera device supports the YUV420_888 reprocessing use case, similar as
+     * OPAQUE_REPROCESSING, This capability requires the camera device to support the
+     * following:</p>
+     * <ul>
+     * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
+     * <li>YUV420_888 is supported as a common format for both input and output, that is,
+     *   StreamConfigurationMap#getOutputSizes(YUV420_888) and
+     *   StreamConfigurationMap#getInputSizes(YUV420_888) return non empty Size[] and have
+     *   common sizes.</li>
+     * <li>android.scaler.availableInputOutputFormatsMap has the required map entries.</li>
+     * <li>Using YUV420_888 does not cause a frame rate drop
+     *   relative to the sensor's maximum capture rate (at that
+     *   resolution), see android.scaler.availableInputOutputFormatsMap for more details.</li>
+     * <li>YUV420_888 will be reprocessable into both YUV_420_888
+     *   and JPEG formats.</li>
+     * <li>The maximum available resolution for YUV420_888 streams
+     *   (both input/output) will match the maximum available
+     *   resolution of JPEG streams.</li>
+     * <li>Only the below controls are effective for reprocessing requests and will be
+     *   present in capture results. The reprocess requests are from the original capture
+     *   results that are assocaited with the intermidate YUV420_888 output buffers.
+     *   All other controls in the reprocess requests will be ignored by the camera device.<ul>
+     * <li>android.jpeg.*</li>
+     * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
+     * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
+     * <li>{@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}</li>
+     * </ul>
+     * </li>
+     * </ul>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7;
+
     //
     // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
     //
@@ -1830,6 +1886,13 @@
      */
     public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2;
 
+    /**
+     * <p>MINIMAL noise reduction is applied without reducing frame rate relative to
+     * sensor output. </p>
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     */
+    public static final int NOISE_REDUCTION_MODE_MINIMAL = 3;
+
     //
     // Enumeration values for CaptureRequest#SENSOR_TEST_PATTERN_MODE
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 0849df8..e1b14cc 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -552,6 +552,8 @@
      * in this matrix result metadata. The transform should keep the magnitude
      * of the output color values within <code>[0, 1.0]</code> (assuming input color
      * values is within the normalized range <code>[0, 1.0]</code>), or clipping may occur.</p>
+     * <p>The valid range of each matrix element varies on different devices, but
+     * values within [-1.5, 3.0] are guaranteed not to be clipped.</p>
      * <p><b>Units</b>: Unitless scale factors</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
@@ -575,6 +577,10 @@
      * TRANSFORM_MATRIX.</p>
      * <p>The gains in the result metadata are the gains actually
      * applied by the camera device to the current frame.</p>
+     * <p>The valid range of gains varies on different devices, but gains
+     * between [1.0, 3.0] are guaranteed not to be clipped. Even if a given
+     * device allows gains below 1.0, this is usually not recommended because
+     * this can create color artifacts.</p>
      * <p><b>Units</b>: Unitless gain factors</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
@@ -1154,7 +1160,7 @@
      * <p>This control (except for MANUAL) is only effective if
      * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
      * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
      * contains MANUAL_SENSOR. Other intent values are always supported.</p>
      * <p><b>Possible values:</b>
      * <ul>
@@ -1239,10 +1245,6 @@
      * update, as if this frame is never captured. This mode can be used in the scenario
      * where the application doesn't want a 3A manual control capture to affect
      * the subsequent auto 3A capture results.</p>
-     * <p>LEGACY mode devices will only support AUTO and USE_SCENE_MODE modes.
-     * LIMITED mode devices will only support OFF and OFF_KEEP_STATE if they
-     * support the MANUAL_SENSOR and MANUAL_POST_PROCSESING capabilities.
-     * FULL mode devices will always support OFF and OFF_KEEP_STATE.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_MODE_OFF OFF}</li>
@@ -1250,9 +1252,12 @@
      *   <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li>
      *   <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li>
      * </ul></p>
+     * <p><b>Available values for this device:</b><br>
+     * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AF_MODE
+     * @see CameraCharacteristics#CONTROL_AVAILABLE_MODES
      * @see #CONTROL_MODE_OFF
      * @see #CONTROL_MODE_AUTO
      * @see #CONTROL_MODE_USE_SCENE_MODE
@@ -1372,6 +1377,10 @@
      * camera device will use the highest-quality enhancement algorithms,
      * even if it slows down capture rate. FAST means the camera device will
      * not slow down capture rate when applying edge enhancement.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
+     * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
+     * The camera device may adjust its internal noise reduction parameters for best
+     * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #EDGE_MODE_OFF OFF}</li>
@@ -1387,6 +1396,7 @@
      *
      * @see CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #EDGE_MODE_OFF
      * @see #EDGE_MODE_FAST
      * @see #EDGE_MODE_HIGH_QUALITY
@@ -1751,18 +1761,28 @@
     /**
      * <p>Mode of operation for the noise reduction algorithm.</p>
      * <p>The noise reduction algorithm attempts to improve image quality by removing
-     * excessive noise added by the capture process, especially in dark conditions.
-     * OFF means no noise reduction will be applied by the camera device.</p>
+     * excessive noise added by the capture process, especially in dark conditions.</p>
+     * <p>OFF means no noise reduction will be applied by the camera device, for both raw and
+     * YUV domain.</p>
+     * <p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,to remove
+     * demosaicing or other processing artifacts. For YUV_REPROCESSING, MINIMAL is same as OFF.
+     * This mode is optional, may not be support by all devices. The application should check
+     * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes} before using it.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
      * even if it slows down capture rate. FAST means the camera device will not
      * slow down capture rate when applying noise filtering.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera device
+     * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
+     * may adjust the noise reduction parameters for best image quality based on the
+     * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+     *   <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
@@ -1773,9 +1793,11 @@
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #NOISE_REDUCTION_MODE_OFF
      * @see #NOISE_REDUCTION_MODE_FAST
      * @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
+     * @see #NOISE_REDUCTION_MODE_MINIMAL
      */
     @PublicKey
     public static final Key<Integer> NOISE_REDUCTION_MODE =
@@ -2416,6 +2438,52 @@
     public static final Key<Boolean> BLACK_LEVEL_LOCK =
             new Key<Boolean>("android.blackLevel.lock", boolean.class);
 
+    /**
+     * <p>The amount of exposure time increase factor applied to the original output
+     * frame by the application processing before sending for reprocessing.</p>
+     * <p>This is optional, and will be supported if the camera device supports YUV_REPROCESSING
+     * capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains YUV_REPROCESSING).</p>
+     * <p>For some YUV reprocessing use cases, the application may choose to filter the original
+     * output frames to effectively reduce the noise to the same level as a frame that was
+     * captured with longer exposure time. To be more specific, assuming the original captured
+     * images were captured with a sensitivity of S and an exposure time of T, the model in
+     * the camera device is that the amount of noise in the image would be approximately what
+     * would be expected if the original capture parameters had been a sensitivity of
+     * S/effectiveExposureFactor and an exposure time of T*effectiveExposureFactor, rather
+     * than S and T respectively. If the captured images were processed by the application
+     * before being sent for reprocessing, then the application may have used image processing
+     * algorithms and/or multi-frame image fusion to reduce the noise in the
+     * application-processed images (input images). By using the effectiveExposureFactor
+     * control, the application can communicate to the camera device the actual noise level
+     * improvement in the application-processed image. With this information, the camera
+     * device can select appropriate noise reduction and edge enhancement parameters to avoid
+     * excessive noise reduction ({@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}) and insufficient edge
+     * enhancement ({@link CaptureRequest#EDGE_MODE android.edge.mode}) being applied to the reprocessed frames.</p>
+     * <p>For example, for multi-frame image fusion use case, the application may fuse
+     * multiple output frames together to a final frame for reprocessing. When N image are
+     * fused into 1 image for reprocessing, the exposure time increase factor could be up to
+     * square root of N (based on a simple photon shot noise model). The camera device will
+     * adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+     * produce the best quality images.</p>
+     * <p>This is relative factor, 1.0 indicates the application hasn't processed the input
+     * buffer in a way that affects its effective exposure time.</p>
+     * <p>This control is only effective for YUV reprocessing capture request. For noise
+     * reduction reprocessing, it is only effective when <code>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} != OFF</code>.
+     * Similarly, for edge enhancement reprocessing, it is only effective when
+     * <code>{@link CaptureRequest#EDGE_MODE android.edge.mode} != OFF</code>.</p>
+     * <p><b>Units</b>: Relative exposure time increase factor.</p>
+     * <p><b>Range of valid values:</b><br>
+     * &gt;= 1.0</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    @PublicKey
+    public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
+            new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 1396940..5bf5b29 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -403,6 +403,8 @@
      * in this matrix result metadata. The transform should keep the magnitude
      * of the output color values within <code>[0, 1.0]</code> (assuming input color
      * values is within the normalized range <code>[0, 1.0]</code>), or clipping may occur.</p>
+     * <p>The valid range of each matrix element varies on different devices, but
+     * values within [-1.5, 3.0] are guaranteed not to be clipped.</p>
      * <p><b>Units</b>: Unitless scale factors</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
@@ -426,6 +428,10 @@
      * TRANSFORM_MATRIX.</p>
      * <p>The gains in the result metadata are the gains actually
      * applied by the camera device to the current frame.</p>
+     * <p>The valid range of gains varies on different devices, but gains
+     * between [1.0, 3.0] are guaranteed not to be clipped. Even if a given
+     * device allows gains below 1.0, this is usually not recommended because
+     * this can create color artifacts.</p>
      * <p><b>Units</b>: Unitless gain factors</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
@@ -1627,7 +1633,7 @@
      * <p>This control (except for MANUAL) is only effective if
      * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
      * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
      * contains MANUAL_SENSOR. Other intent values are always supported.</p>
      * <p><b>Possible values:</b>
      * <ul>
@@ -1855,10 +1861,6 @@
      * update, as if this frame is never captured. This mode can be used in the scenario
      * where the application doesn't want a 3A manual control capture to affect
      * the subsequent auto 3A capture results.</p>
-     * <p>LEGACY mode devices will only support AUTO and USE_SCENE_MODE modes.
-     * LIMITED mode devices will only support OFF and OFF_KEEP_STATE if they
-     * support the MANUAL_SENSOR and MANUAL_POST_PROCSESING capabilities.
-     * FULL mode devices will always support OFF and OFF_KEEP_STATE.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_MODE_OFF OFF}</li>
@@ -1866,9 +1868,12 @@
      *   <li>{@link #CONTROL_MODE_USE_SCENE_MODE USE_SCENE_MODE}</li>
      *   <li>{@link #CONTROL_MODE_OFF_KEEP_STATE OFF_KEEP_STATE}</li>
      * </ul></p>
+     * <p><b>Available values for this device:</b><br>
+     * {@link CameraCharacteristics#CONTROL_AVAILABLE_MODES android.control.availableModes}</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureRequest#CONTROL_AF_MODE
+     * @see CameraCharacteristics#CONTROL_AVAILABLE_MODES
      * @see #CONTROL_MODE_OFF
      * @see #CONTROL_MODE_AUTO
      * @see #CONTROL_MODE_USE_SCENE_MODE
@@ -1988,6 +1993,10 @@
      * camera device will use the highest-quality enhancement algorithms,
      * even if it slows down capture rate. FAST means the camera device will
      * not slow down capture rate when applying edge enhancement.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
+     * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
+     * The camera device may adjust its internal noise reduction parameters for best
+     * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #EDGE_MODE_OFF OFF}</li>
@@ -2003,6 +2012,7 @@
      *
      * @see CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #EDGE_MODE_OFF
      * @see #EDGE_MODE_FAST
      * @see #EDGE_MODE_HIGH_QUALITY
@@ -2465,18 +2475,28 @@
     /**
      * <p>Mode of operation for the noise reduction algorithm.</p>
      * <p>The noise reduction algorithm attempts to improve image quality by removing
-     * excessive noise added by the capture process, especially in dark conditions.
-     * OFF means no noise reduction will be applied by the camera device.</p>
+     * excessive noise added by the capture process, especially in dark conditions.</p>
+     * <p>OFF means no noise reduction will be applied by the camera device, for both raw and
+     * YUV domain.</p>
+     * <p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,to remove
+     * demosaicing or other processing artifacts. For YUV_REPROCESSING, MINIMAL is same as OFF.
+     * This mode is optional, may not be support by all devices. The application should check
+     * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes} before using it.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
      * even if it slows down capture rate. FAST means the camera device will not
      * slow down capture rate when applying noise filtering.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera device
+     * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
+     * may adjust the noise reduction parameters for best image quality based on the
+     * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+     *   <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
@@ -2487,9 +2507,11 @@
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #NOISE_REDUCTION_MODE_OFF
      * @see #NOISE_REDUCTION_MODE_FAST
      * @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
+     * @see #NOISE_REDUCTION_MODE_MINIMAL
      */
     @PublicKey
     public static final Key<Integer> NOISE_REDUCTION_MODE =
@@ -3647,6 +3669,52 @@
     public static final Key<Long> SYNC_FRAME_NUMBER =
             new Key<Long>("android.sync.frameNumber", long.class);
 
+    /**
+     * <p>The amount of exposure time increase factor applied to the original output
+     * frame by the application processing before sending for reprocessing.</p>
+     * <p>This is optional, and will be supported if the camera device supports YUV_REPROCESSING
+     * capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains YUV_REPROCESSING).</p>
+     * <p>For some YUV reprocessing use cases, the application may choose to filter the original
+     * output frames to effectively reduce the noise to the same level as a frame that was
+     * captured with longer exposure time. To be more specific, assuming the original captured
+     * images were captured with a sensitivity of S and an exposure time of T, the model in
+     * the camera device is that the amount of noise in the image would be approximately what
+     * would be expected if the original capture parameters had been a sensitivity of
+     * S/effectiveExposureFactor and an exposure time of T*effectiveExposureFactor, rather
+     * than S and T respectively. If the captured images were processed by the application
+     * before being sent for reprocessing, then the application may have used image processing
+     * algorithms and/or multi-frame image fusion to reduce the noise in the
+     * application-processed images (input images). By using the effectiveExposureFactor
+     * control, the application can communicate to the camera device the actual noise level
+     * improvement in the application-processed image. With this information, the camera
+     * device can select appropriate noise reduction and edge enhancement parameters to avoid
+     * excessive noise reduction ({@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}) and insufficient edge
+     * enhancement ({@link CaptureRequest#EDGE_MODE android.edge.mode}) being applied to the reprocessed frames.</p>
+     * <p>For example, for multi-frame image fusion use case, the application may fuse
+     * multiple output frames together to a final frame for reprocessing. When N image are
+     * fused into 1 image for reprocessing, the exposure time increase factor could be up to
+     * square root of N (based on a simple photon shot noise model). The camera device will
+     * adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+     * produce the best quality images.</p>
+     * <p>This is relative factor, 1.0 indicates the application hasn't processed the input
+     * buffer in a way that affects its effective exposure time.</p>
+     * <p>This control is only effective for YUV reprocessing capture request. For noise
+     * reduction reprocessing, it is only effective when <code>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} != OFF</code>.
+     * Similarly, for edge enhancement reprocessing, it is only effective when
+     * <code>{@link CaptureRequest#EDGE_MODE android.edge.mode} != OFF</code>.</p>
+     * <p><b>Units</b>: Relative exposure time increase factor.</p>
+     * <p><b>Range of valid values:</b><br>
+     * &gt;= 1.0</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    @PublicKey
+    public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
+            new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 6fc99ac..33d539c2 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -530,9 +530,9 @@
         int uPixStride = uPlane.getPixelStride();
 
         byte[] yuvPixel = { 0, 0, 0 };
-        byte[] yFullRow = new byte[yPixStride * width];
-        byte[] uFullRow = new byte[uPixStride * width / 2];
-        byte[] vFullRow = new byte[vPixStride * width / 2];
+        byte[] yFullRow = new byte[yPixStride * (width - 1) + 1];
+        byte[] uFullRow = new byte[uPixStride * (width / 2 - 1) + 1];
+        byte[] vFullRow = new byte[vPixStride * (width / 2 - 1) + 1];
         byte[] finalRow = new byte[BYTES_PER_RGB_PIX * width];
         for (int i = 0; i < height; i++) {
             int halfH = i / 2;
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 347db05..802b938 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -474,6 +474,15 @@
 
             m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step));
         }
+
+        /*
+         * control.aeLockAvailable
+         */
+        {
+            boolean aeLockAvailable = p.isAutoExposureLockSupported();
+
+            m.set(CONTROL_AE_LOCK_AVAILABLE, aeLockAvailable);
+        }
     }
 
 
@@ -571,6 +580,16 @@
                 Log.v(TAG, "mapControlAwb - control.awbAvailableModes set to " +
                         ListUtils.listToString(awbAvail));
             }
+
+
+            /*
+             * control.awbLockAvailable
+             */
+            {
+                boolean awbLockAvailable = p.isAutoWhiteBalanceLockSupported();
+
+                m.set(CONTROL_AWB_LOCK_AVAILABLE, awbLockAvailable);
+            }
         }
     }
 
@@ -618,17 +637,44 @@
         /*
          * android.control.availableSceneModes
          */
+        int maxNumDetectedFaces = p.getMaxNumDetectedFaces();
         List<String> sceneModes = p.getSupportedSceneModes();
         List<Integer> supportedSceneModes =
                 ArrayUtils.convertStringListToIntList(sceneModes, sLegacySceneModes, sSceneModes);
-        if (supportedSceneModes == null) { // camera1 doesn't support scene mode settings
-            supportedSceneModes = new ArrayList<Integer>();
-            supportedSceneModes.add(CONTROL_SCENE_MODE_DISABLED); // disabled is always available
+
+        // Special case where the only scene mode listed is AUTO => no scene mode
+        if (sceneModes != null && sceneModes.size() == 1 &&
+                sceneModes.get(0) == Parameters.SCENE_MODE_AUTO) {
+            supportedSceneModes = null;
         }
-        if (p.getMaxNumDetectedFaces() > 0) { // always supports FACE_PRIORITY when face detecting
-            supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
+
+        boolean sceneModeSupported = true;
+        if (supportedSceneModes == null && maxNumDetectedFaces == 0) {
+            sceneModeSupported = false;
         }
-        m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
+
+        if (sceneModeSupported) {
+            if (supportedSceneModes == null) {
+                supportedSceneModes = new ArrayList<Integer>();
+            }
+            if (maxNumDetectedFaces > 0) { // always supports FACE_PRIORITY when face detecting
+                supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
+            }
+            // Remove all DISABLED occurrences
+            if (supportedSceneModes.contains(CONTROL_SCENE_MODE_DISABLED)) {
+                while(supportedSceneModes.remove(new Integer(CONTROL_SCENE_MODE_DISABLED))) {}
+            }
+            m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
+        } else {
+            m.set(CONTROL_AVAILABLE_SCENE_MODES, new int[] {CONTROL_SCENE_MODE_DISABLED});
+        }
+
+        /*
+         * android.control.availableModes
+         */
+        m.set(CONTROL_AVAILABLE_MODES, sceneModeSupported ?
+                new int[] { CONTROL_MODE_AUTO, CONTROL_MODE_USE_SCENE_MODE } :
+                new int[] { CONTROL_MODE_AUTO });
     }
 
     private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 6535a4e..f1f2f0c 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -44,6 +44,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import static com.android.internal.util.Preconditions.*;
 
@@ -68,7 +69,7 @@
     // For slightly more spammy messages that will get repeated every frame
     private static final boolean VERBOSE =
             Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.VERBOSE);
-    private final Camera mCamera;
+    private Camera mCamera;
     private final CameraCharacteristics mCharacteristics;
 
     private final CameraDeviceState mDeviceState;
@@ -83,8 +84,8 @@
     private static final int MAX_IN_FLIGHT_REQUESTS = 2;
 
     private static final int PREVIEW_FRAME_TIMEOUT = 1000; // ms
-    private static final int JPEG_FRAME_TIMEOUT = 3000; // ms (same as CTS for API2)
-    private static final int REQUEST_COMPLETE_TIMEOUT = 3000; // ms (same as JPEG timeout)
+    private static final int JPEG_FRAME_TIMEOUT = 4000; // ms (same as CTS for API2)
+    private static final int REQUEST_COMPLETE_TIMEOUT = JPEG_FRAME_TIMEOUT; // ms (same as JPEG timeout)
 
     private static final float ASPECT_RATIO_TOLERANCE = 0.01f;
     private boolean mPreviewRunning = false;
@@ -108,6 +109,8 @@
     private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview");
     private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests");
 
+    private final AtomicBoolean mQuit = new AtomicBoolean(false);
+
     // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write
     // limitations for (b/17379185).
     private static final boolean USE_BLOB_FORMAT_OVERRIDE = true;
@@ -325,7 +328,15 @@
             Log.d(TAG, "configureOutputs with " + outputsStr);
         }
 
-        stopPreview();
+        try {
+            stopPreview();
+        }  catch (RuntimeException e) {
+            Log.e(TAG, "Received device exception in configure call: ", e);
+            mDeviceState.setError(
+                    CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+            return;
+        }
+
         /*
          * Try to release the previous preview's surface texture earlier if we end up
          * using a different one; this also reduces the likelihood of getting into a deadlock
@@ -335,6 +346,11 @@
             mCamera.setPreviewTexture(/*surfaceTexture*/null);
         } catch (IOException e) {
             Log.w(TAG, "Failed to clear prior SurfaceTexture, may cause GL deadlock: ", e);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Received device exception in configure call: ", e);
+            mDeviceState.setError(
+                    CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+            return;
         }
 
         if (mGLThreadManager != null) {
@@ -470,7 +486,14 @@
             mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback);
         }
 
-        mCamera.setParameters(mParams);
+        try {
+            mCamera.setParameters(mParams);
+        } catch (RuntimeException e) {
+                Log.e(TAG, "Received device exception while configuring: ", e);
+                mDeviceState.setError(
+                        CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+
+        }
     }
 
     private void resetJpegSurfaceFormats(Collection<Surface> surfaces) {
@@ -793,7 +816,7 @@
                             }
 
                         } catch (IOException e) {
-                            Log.e(TAG, "Received device exception: ", e);
+                            Log.e(TAG, "Received device exception during capture call: ", e);
                             mDeviceState.setError(
                                     CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
                             break;
@@ -802,6 +825,11 @@
                             mDeviceState.setError(
                                     CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
                             break;
+                        } catch (RuntimeException e) {
+                            Log.e(TAG, "Received device exception during capture call: ", e);
+                            mDeviceState.setError(
+                                    CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+                            break;
                         }
 
                         if (paramsChanged) {
@@ -878,9 +906,11 @@
                     }
                     if (mGLThreadManager != null) {
                         mGLThreadManager.quit();
+                        mGLThreadManager = null;
                     }
                     if (mCamera != null) {
                         mCamera.release();
+                        mCamera = null;
                     }
                     resetJpegSurfaceFormats(mCallbackOutputs);
                     break;
@@ -942,14 +972,16 @@
      * Quit the request thread, and clean up everything.
      */
     public void quit() {
-        Handler handler = mRequestThread.waitAndGetHandler();
-        handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP));
-        mRequestThread.quitSafely();
-        try {
-            mRequestThread.join();
-        } catch (InterruptedException e) {
-            Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.",
-                    mRequestThread.getName(), mRequestThread.getId()));
+        if (!mQuit.getAndSet(true)) {  // Avoid sending messages on dead thread's handler.
+            Handler handler = mRequestThread.waitAndGetHandler();
+            handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP));
+            mRequestThread.quitSafely();
+            try {
+                mRequestThread.join();
+            } catch (InterruptedException e) {
+                Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.",
+                        mRequestThread.getName(), mRequestThread.getId()));
+            }
         }
     }
 
diff --git a/core/java/android/midi/MidiDevice.java b/core/java/android/midi/MidiDevice.java
index 8aaa86d..b91aedf 100644
--- a/core/java/android/midi/MidiDevice.java
+++ b/core/java/android/midi/MidiDevice.java
@@ -30,6 +30,7 @@
  * This class is used for sending and receiving data to and from an MIDI device
  * Instances of this class are created by {@link MidiManager#openDevice}.
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public final class MidiDevice {
diff --git a/core/java/android/midi/MidiDeviceInfo.java b/core/java/android/midi/MidiDeviceInfo.java
index 5cf62b5..dde2669 100644
--- a/core/java/android/midi/MidiDeviceInfo.java
+++ b/core/java/android/midi/MidiDeviceInfo.java
@@ -28,6 +28,7 @@
  * This class is just an immutable object to encapsulate the MIDI device description.
  * Use the MidiDevice class to actually communicate with devices.
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public class MidiDeviceInfo implements Parcelable {
@@ -45,7 +46,7 @@
     public static final int TYPE_VIRTUAL = 2;
 
     private final int mType;    // USB or virtual
-    private final int mId;  // unique ID generated by MidiService
+    private final int mId;      // unique ID generated by MidiService
     private final int mInputPortCount;
     private final int mOutputPortCount;
     private final Bundle mProperties;
diff --git a/core/java/android/midi/MidiDeviceServer.java b/core/java/android/midi/MidiDeviceServer.java
index ccb2e0c..7499934 100644
--- a/core/java/android/midi/MidiDeviceServer.java
+++ b/core/java/android/midi/MidiDeviceServer.java
@@ -25,7 +25,14 @@
 import java.io.IOException;
 import java.util.ArrayList;
 
-/** @hide */
+/**
+ * This class is used to provide the implemention of MIDI device.
+ * Applications may call {@link MidiManager#createDeviceServer}
+ * to create an instance of this class to implement a virtual MIDI device.
+ *
+ * CANDIDATE FOR PUBLIC API
+ * @hide
+ */
 public final class MidiDeviceServer implements Closeable {
     private static final String TAG = "MidiDeviceServer";
 
diff --git a/core/java/android/midi/MidiInputPort.java b/core/java/android/midi/MidiInputPort.java
index 88ace5f..51c47dd 100644
--- a/core/java/android/midi/MidiInputPort.java
+++ b/core/java/android/midi/MidiInputPort.java
@@ -26,6 +26,7 @@
 /**
  * This class is used for sending data to a port on a MIDI device
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public class MidiInputPort extends MidiPort implements MidiReceiver {
diff --git a/core/java/android/midi/MidiManager.java b/core/java/android/midi/MidiManager.java
index 2c1c7bf..8aa8395 100644
--- a/core/java/android/midi/MidiManager.java
+++ b/core/java/android/midi/MidiManager.java
@@ -35,6 +35,7 @@
  * {@samplecode
  * MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);}
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public class MidiManager {
@@ -184,7 +185,7 @@
      * @param properties a {@link android.os.Bundle} containing properties describing the device
      * @param isPrivate true if this device should only be visible and accessible to apps
      *                  with the same UID as the caller
-     * @return a {@link MidiVirtualDevice} object to locally represent the device
+     * @return a {@link MidiDeviceServer} object to locally represent the device
      */
     public MidiDeviceServer createDeviceServer(int numInputPorts, int numOutputPorts,
             Bundle properties, boolean isPrivate) {
diff --git a/core/java/android/midi/MidiOutputPort.java b/core/java/android/midi/MidiOutputPort.java
index 00b7bad..332b431 100644
--- a/core/java/android/midi/MidiOutputPort.java
+++ b/core/java/android/midi/MidiOutputPort.java
@@ -26,8 +26,9 @@
 import java.util.ArrayList;
 
 /**
- * This class is used for receiving data to a port on a MIDI device
+ * This class is used for receiving data from a port on a MIDI device
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public class MidiOutputPort extends MidiPort implements MidiSender {
@@ -85,8 +86,9 @@
                     }
                 }
             } catch (IOException e) {
-                Log.e(TAG, "read failed");
                 // report I/O failure
+                Log.e(TAG, "read failed");
+            } finally {
                 IoUtils.closeQuietly(mInputStream);
                 onIOException();
             }
diff --git a/core/java/android/midi/MidiPort.java b/core/java/android/midi/MidiPort.java
index 44d1a88..7512a90 100644
--- a/core/java/android/midi/MidiPort.java
+++ b/core/java/android/midi/MidiPort.java
@@ -24,6 +24,7 @@
  * This class represents a MIDI input or output port.
  * Base class for {@link MidiInputPort} and {@link MidiOutputPort}
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 abstract public class MidiPort implements Closeable {
diff --git a/core/java/android/midi/MidiReceiver.java b/core/java/android/midi/MidiReceiver.java
index a4e1a10..fdfe51a 100644
--- a/core/java/android/midi/MidiReceiver.java
+++ b/core/java/android/midi/MidiReceiver.java
@@ -19,13 +19,14 @@
 import java.io.IOException;
 
 /**
- * Interface for receiving events from a MIDI device.
+ * Interface for receiving data from a MIDI device.
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public interface MidiReceiver {
     /**
-     * Called to pass a MIDI event to the receiver.
+     * Called to pass MIDI data to the receiver.
      *
      * NOTE: the msg array parameter is only valid within the context of this call.
      * The msg bytes should be copied by the receiver rather than retaining a reference
@@ -33,9 +34,9 @@
      * Also, modifying the contents of the msg array parameter may result in other receivers
      * in the same application receiving incorrect values in their onPost() method.
      *
-     * @param msg a byte array containing the MIDI message
-     * @param offset the offset of the first byte of the message in the byte array
-     * @param count the number of bytes in the message
+     * @param msg a byte array containing the MIDI data
+     * @param offset the offset of the first byte of the data in the byte array
+     * @param count the number of bytes of MIDI data in the array
      * @param timestamp the timestamp of the message (based on {@link java.lang.System#nanoTime}
      * @throws IOException
      */
diff --git a/core/java/android/midi/MidiSender.java b/core/java/android/midi/MidiSender.java
index 7958a06..2b7afad 100644
--- a/core/java/android/midi/MidiSender.java
+++ b/core/java/android/midi/MidiSender.java
@@ -20,6 +20,7 @@
  * Interface provided by a device to allow attaching
  * MidiReceivers to a MIDI device.
  *
+ * CANDIDATE FOR PUBLIC API
  * @hide
  */
 public interface MidiSender {
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 6654577..27096b1 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -159,6 +159,8 @@
      *     instead. The Apache HTTP client is no longer maintained and may be removed in a future
      *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
      *     for further details.
+     *
+     * @removed
      */
     @Deprecated
     public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 365f2b6..37ee961 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -188,6 +188,7 @@
         for (InetAddress dnsServer : dnsServers) {
             NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
         }
+        dest.writeString(domains);
     }
 
     protected static void readFromParcel(StaticIpConfiguration s, Parcel in) {
@@ -198,5 +199,6 @@
         for (int i = 0; i < size; i++) {
             s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
         }
+        s.domains = in.readString();
     }
 }
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 2099c3f..bf3d9aa 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -366,6 +366,7 @@
     public String toSafeString() {
         String scheme = getScheme();
         String ssp = getSchemeSpecificPart();
+        String authority = null;
         if (scheme != null) {
             if (scheme.equalsIgnoreCase("tel") || scheme.equalsIgnoreCase("sip")
                     || scheme.equalsIgnoreCase("sms") || scheme.equalsIgnoreCase("smsto")
@@ -384,6 +385,9 @@
                     }
                 }
                 return builder.toString();
+            } else if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
+                ssp = null;
+                authority = "//" + getAuthority() + "/...";
             }
         }
         // Not a sensitive scheme, but let's still be conservative about
@@ -397,6 +401,9 @@
         if (ssp != null) {
             builder.append(ssp);
         }
+        if (authority != null) {
+            builder.append(authority);
+        }
         return builder.toString();
     }
 
@@ -1742,7 +1749,7 @@
      *
      * @return normalized Uri (never null)
      * @see {@link android.content.Intent#setData}
-     * @see {@link #setNormalizedData}
+     * @see {@link android.content.Intent#setDataAndNormalize}
      */
     public Uri normalizeScheme() {
         String scheme = getScheme();
diff --git a/core/java/android/os/IProcessInfoService.aidl b/core/java/android/os/IProcessInfoService.aidl
new file mode 100644
index 0000000..c98daa2
--- /dev/null
+++ b/core/java/android/os/IProcessInfoService.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/** {@hide} */
+interface IProcessInfoService
+{
+    /**
+     * For each PID in the given input array, write the current process state
+     * for that process into the output array, or ActivityManager.PROCESS_STATE_NONEXISTENT
+     * to indicate that no process with the given PID exists.
+     */
+    void getProcessStatesFromPids(in int[] pids, out int[] states);
+}
+
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index bedc695..3d5215b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -276,7 +276,7 @@
 
     private static native byte[] nativeMarshall(long nativePtr);
     private static native void nativeUnmarshall(
-            long nativePtr, byte[] data, int offest, int length);
+            long nativePtr, byte[] data, int offset, int length);
     private static native void nativeAppendFrom(
             long thisNativePtr, long otherNativePtr, int offset, int length);
     private static native boolean nativeHasFileDescriptors(long nativePtr);
@@ -438,8 +438,8 @@
     /**
      * Set the bytes in data to be the raw bytes of this Parcel.
      */
-    public final void unmarshall(byte[] data, int offest, int length) {
-        nativeUnmarshall(mNativePtr, data, offest, length);
+    public final void unmarshall(byte[] data, int offset, int length) {
+        nativeUnmarshall(mNativePtr, data, offset, length);
     }
 
     public final void appendFrom(Parcel parcel, int offset, int length) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8307d9b..d52dd30 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -835,6 +835,21 @@
     }
 
     /**
+     * Turn off the device.
+     *
+     * @param confirm If true, shows a shutdown confirmation dialog.
+     * @param wait If true, this call waits for the shutdown to complete and does not return.
+     *
+     * @hide
+     */
+    public void shutdown(boolean confirm, boolean wait) {
+        try {
+            mService.shutdown(confirm, wait);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
      * This broadcast is only sent to registered receivers.
      */
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index 30f0c6a..90d30d6 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -45,11 +45,22 @@
     private static final int VALID_COLOR_MODES =
             COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;
 
+    /** Duplex mode: No duplexing. */
+    public static final int DUPLEX_MODE_NONE = 1 << 0;
+    /** Duplex mode: Pages are turned sideways along the long edge - like a book. */
+    public static final int DUPLEX_MODE_LONG_EDGE = 1 << 1;
+    /** Duplex mode: Pages are turned upwards along the short edge - like a notpad. */
+    public static final int DUPLEX_MODE_SHORT_EDGE = 1 << 2;
+
+    private static final int VALID_DUPLEX_MODES =
+            DUPLEX_MODE_NONE | DUPLEX_MODE_LONG_EDGE | DUPLEX_MODE_SHORT_EDGE;
+
     private MediaSize mMediaSize;
     private Resolution mResolution;
     private Margins mMinMargins;
 
     private int mColorMode;
+    private int mDuplexMode = DUPLEX_MODE_NONE;
 
     PrintAttributes() {
         /* hide constructor */
@@ -60,6 +71,7 @@
         mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
         mMinMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
         mColorMode = parcel.readInt();
+        mDuplexMode = parcel.readInt();
     }
 
     /**
@@ -74,7 +86,7 @@
     /**
      * Sets the media size.
      *
-     * @param The media size.
+     * @param mediaSize The media size.
      *
      * @hide
      */
@@ -94,7 +106,7 @@
     /**
      * Sets the resolution.
      *
-     * @param The resolution.
+     * @param resolution The resolution.
      *
      * @hide
      */
@@ -130,7 +142,7 @@
      * </strong>
      * </p>
      *
-     * @param The margins.
+     * @param margins The margins.
      *
      * @hide
      */
@@ -153,7 +165,7 @@
     /**
      * Sets the color mode.
      *
-     * @param The color mode.
+     * @param colorMode The color mode.
      *
      * @see #COLOR_MODE_MONOCHROME
      * @see #COLOR_MODE_COLOR
@@ -179,6 +191,35 @@
     }
 
     /**
+     * Gets the duplex mode.
+     *
+     * @return The duplex mode.
+     *
+     * @see #DUPLEX_MODE_NONE
+     * @see #DUPLEX_MODE_LONG_EDGE
+     * @see #DUPLEX_MODE_SHORT_EDGE
+     */
+    public int getDuplexMode() {
+        return mDuplexMode;
+    }
+
+    /**
+     * Sets the duplex mode.
+     *
+     * @param duplexMode The duplex mode.
+     *
+     * @see #DUPLEX_MODE_NONE
+     * @see #DUPLEX_MODE_LONG_EDGE
+     * @see #DUPLEX_MODE_SHORT_EDGE
+     *
+     * @hide
+     */
+    public void setDuplexMode(int duplexMode) {
+        enforceValidDuplexMode(duplexMode);
+        mDuplexMode = duplexMode;
+    }
+
+    /**
      * Gets a new print attributes instance which is in portrait orientation,
      * which is the media size is in portrait and all orientation dependent
      * attributes such as resolution and margins are properly adjusted.
@@ -211,6 +252,7 @@
         attributes.setMinMargins(getMinMargins());
 
         attributes.setColorMode(getColorMode());
+        attributes.setDuplexMode(getDuplexMode());
 
         return attributes;
     }
@@ -248,6 +290,7 @@
         attributes.setMinMargins(getMinMargins());
 
         attributes.setColorMode(getColorMode());
+        attributes.setDuplexMode(getDuplexMode());
 
         return attributes;
     }
@@ -273,6 +316,7 @@
             parcel.writeInt(0);
         }
         parcel.writeInt(mColorMode);
+        parcel.writeInt(mDuplexMode);
     }
 
     @Override
@@ -285,6 +329,7 @@
         final int prime = 31;
         int result = 1;
         result = prime * result + mColorMode;
+        result = prime * result + mDuplexMode;
         result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
         result = prime * result + ((mMediaSize == null) ? 0 : mMediaSize.hashCode());
         result = prime * result + ((mResolution == null) ? 0 : mResolution.hashCode());
@@ -306,6 +351,9 @@
         if (mColorMode != other.mColorMode) {
             return false;
         }
+        if (mDuplexMode != other.mDuplexMode) {
+            return false;
+        }
         if (mMinMargins == null) {
             if (other.mMinMargins != null) {
                 return false;
@@ -344,6 +392,7 @@
         builder.append(", resolution: ").append(mResolution);
         builder.append(", minMargins: ").append(mMinMargins);
         builder.append(", colorMode: ").append(colorModeToString(mColorMode));
+        builder.append(", duplexMode: ").append(duplexModeToString(mDuplexMode));
         builder.append("}");
         return builder.toString();
     }
@@ -354,6 +403,7 @@
         mResolution = null;
         mMinMargins = null;
         mColorMode = 0;
+        mDuplexMode = DUPLEX_MODE_NONE;
     }
 
     /**
@@ -364,6 +414,7 @@
         mResolution = other.mResolution;
         mMinMargins = other.mMinMargins;
         mColorMode = other.mColorMode;
+        mDuplexMode = other.mDuplexMode;
     }
 
     /**
@@ -1270,17 +1321,41 @@
             case COLOR_MODE_COLOR: {
                 return "COLOR_MODE_COLOR";
             }
-            default:
+            default: {
                 return "COLOR_MODE_UNKNOWN";
+            }
+        }
+    }
+
+    static String duplexModeToString(int duplexMode) {
+        switch (duplexMode) {
+            case DUPLEX_MODE_NONE: {
+                return "DUPLEX_MODE_NONE";
+            }
+            case DUPLEX_MODE_LONG_EDGE: {
+                return "DUPLEX_MODE_LONG_EDGE";
+            }
+            case DUPLEX_MODE_SHORT_EDGE: {
+                return "DUPLEX_MODE_SHORT_EDGE";
+            }
+            default: {
+                return "DUPLEX_MODE_UNKNOWN";
+            }
         }
     }
 
     static void enforceValidColorMode(int colorMode) {
-        if ((colorMode & VALID_COLOR_MODES) == 0 && Integer.bitCount(colorMode) == 1) {
+        if ((colorMode & VALID_COLOR_MODES) == 0 || Integer.bitCount(colorMode) != 1) {
             throw new IllegalArgumentException("invalid color mode: " + colorMode);
         }
     }
 
+    static void enforceValidDuplexMode(int duplexMode) {
+        if ((duplexMode & VALID_DUPLEX_MODES) == 0 || Integer.bitCount(duplexMode) != 1) {
+            throw new IllegalArgumentException("invalid duplex mode: " + duplexMode);
+        }
+    }
+
     /**
      * Builder for creating {@link PrintAttributes}.
      */
@@ -1331,15 +1406,31 @@
          * @see PrintAttributes#COLOR_MODE_COLOR
          */
         public Builder setColorMode(int colorMode) {
-            if (Integer.bitCount(colorMode) > 1) {
-                throw new IllegalArgumentException("can specify at most one colorMode bit.");
-            }
             mAttributes.setColorMode(colorMode);
             return this;
         }
 
         /**
+         * Sets the duplex mode.
+         *
+         * @param duplexMode A valid duplex mode or zero.
+         * @return This builder.
+         *
+         * @see PrintAttributes#DUPLEX_MODE_NONE
+         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
+         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
+         */
+        public Builder setDuplexMode(int duplexMode) {
+            mAttributes.setDuplexMode(duplexMode);
+            return this;
+        }
+
+        /**
          * Creates a new {@link PrintAttributes} instance.
+         * <p>
+         * If you do not specify a duplex mode, the default
+         * {@link #DUPLEX_MODE_NONE} will be used.
+         * </p>
          *
          * @return The new instance.
          */
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index 806a89d8..96f3185 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -47,7 +47,8 @@
     private static final int PROPERTY_MEDIA_SIZE = 0;
     private static final int PROPERTY_RESOLUTION = 1;
     private static final int PROPERTY_COLOR_MODE = 2;
-    private static final int PROPERTY_COUNT = 3;
+    private static final int PROPERTY_DUPLEX_MODE = 3;
+    private static final int PROPERTY_COUNT = 4;
 
     private static final Margins DEFAULT_MARGINS = new Margins(0,  0,  0,  0);
 
@@ -56,6 +57,7 @@
     private List<Resolution> mResolutions;
 
     private int mColorModes;
+    private int mDuplexModes;
 
     private final int[] mDefaults = new int[PROPERTY_COUNT];
 
@@ -106,6 +108,7 @@
         }
 
         mColorModes = other.mColorModes;
+        mDuplexModes = other.mDuplexModes;
 
         final int defaultCount = other.mDefaults.length;
         for (int i = 0; i < defaultCount; i++) {
@@ -154,6 +157,19 @@
     }
 
     /**
+     * Gets the bit mask of supported duplex modes.
+     *
+     * @return The bit mask of supported duplex modes.
+     *
+     * @see PrintAttributes#DUPLEX_MODE_NONE
+     * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
+     * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
+     */
+    public int getDuplexModes() {
+        return mDuplexModes;
+    }
+
+    /**
      * Gets the default print attributes.
      *
      * @return The default attributes.
@@ -178,6 +194,11 @@
             builder.setColorMode(colorMode);
         }
 
+        final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
+        if (duplexMode > 0) {
+            builder.setDuplexMode(duplexMode);
+        }
+
         return builder.build();
     }
 
@@ -187,6 +208,7 @@
         readResolutions(parcel);
 
         mColorModes = parcel.readInt();
+        mDuplexModes = parcel.readInt();
 
         readDefaults(parcel);
     }
@@ -203,6 +225,7 @@
         writeResolutions(parcel);
 
         parcel.writeInt(mColorModes);
+        parcel.writeInt(mDuplexModes);
 
         writeDefaults(parcel);
     }
@@ -215,6 +238,7 @@
         result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
         result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
         result = prime * result + mColorModes;
+        result = prime * result + mDuplexModes;
         result = prime * result + Arrays.hashCode(mDefaults);
         return result;
     }
@@ -255,6 +279,9 @@
         if (mColorModes != other.mColorModes) {
             return false;
         }
+        if (mDuplexModes != other.mDuplexModes) {
+            return false;
+        }
         if (!Arrays.equals(mDefaults, other.mDefaults)) {
             return false;
         }
@@ -269,6 +296,7 @@
         builder.append(", mediaSizes=").append(mMediaSizes);
         builder.append(", resolutions=").append(mResolutions);
         builder.append(", colorModes=").append(colorModesToString());
+        builder.append(", duplexModes=").append(duplexModesToString());
         builder.append("\"}");
         return builder.toString();
     }
@@ -289,6 +317,22 @@
         return builder.toString();
     }
 
+    private String duplexModesToString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append('[');
+        int duplexModes = mDuplexModes;
+        while (duplexModes != 0) {
+            final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
+            duplexModes &= ~duplexMode;
+            if (builder.length() > 1) {
+                builder.append(", ");
+            }
+            builder.append(PrintAttributes.duplexModeToString(duplexMode));
+        }
+        builder.append(']');
+        return builder.toString();
+    }
+
     private void writeMediaSizes(Parcel parcel) {
         if (mMediaSizes == null) {
             parcel.writeInt(0);
@@ -495,19 +539,51 @@
                 currentModes &= ~currentMode;
                 PrintAttributes.enforceValidColorMode(currentMode);
             }
-            if ((colorModes & defaultColorMode) == 0) {
-                throw new IllegalArgumentException("Default color mode not in color modes.");
-            }
-            PrintAttributes.enforceValidColorMode(colorModes);
+            PrintAttributes.enforceValidColorMode(defaultColorMode);
             mPrototype.mColorModes = colorModes;
             mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
             return this;
         }
 
         /**
+         * Sets the duplex modes.
+         * <p>
+         * <strong>Required:</strong> No
+         * </p>
+         *
+         * @param duplexModes The duplex mode bit mask.
+         * @param defaultDuplexMode The default duplex mode.
+         * @return This builder.
+         *
+         * @throws IllegalArgumentException If duplex modes contains an invalid
+         *         mode bit or if the default duplex mode is invalid.
+         *
+         * @see PrintAttributes#DUPLEX_MODE_NONE
+         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
+         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
+         */
+        public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
+            int currentModes = duplexModes;
+            while (currentModes > 0) {
+                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
+                currentModes &= ~currentMode;
+                PrintAttributes.enforceValidDuplexMode(currentMode);
+            }
+            PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
+            mPrototype.mDuplexModes = duplexModes;
+            mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
+            return this;
+        }
+
+        /**
          * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
          * required properties have been specified. See individual methods
          * in this class for reference about required attributes.
+         * <p>
+         * <strong>Note:</strong> If you do not add supported duplex modes,
+         * {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
+         * as the only supported mode and also as the default duplex mode.
+         * </p>
          *
          * @return A new {@link PrinterCapabilitiesInfo}.
          *
@@ -532,6 +608,10 @@
             if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
                 throw new IllegalStateException("No default color mode specified.");
             }
+            if (mPrototype.mDuplexModes == 0) {
+                setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
+                        PrintAttributes.DUPLEX_MODE_NONE);
+            }
             if (mPrototype.mMinMargins == null) {
                 throw new IllegalArgumentException("margins cannot be null");
             }
@@ -558,4 +638,3 @@
         }
     };
 }
-
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index ae95854..7ed1649 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -192,7 +192,7 @@
 
     /**
      * If you declared an optional activity with advanced print options via the
-     * {@link R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity}
+     * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity}
      * attribute, this extra is used to pass in the currently constructed {@link
      * PrintJobInfo} to your activity allowing you to modify it. After you are
      * done, you must return the modified {@link PrintJobInfo} via the same extra.
@@ -224,7 +224,7 @@
 
     /**
      * If you declared an optional activity with advanced print options via the
-     * {@link R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity}
+     * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity}
      * attribute, this extra is used to pass in the currently selected printer's
      * {@link android.print.PrinterInfo} to your activity allowing you to inspect it.
      *
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 7dd559c..67ac043 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1434,9 +1434,9 @@
         * and {@link #CONTENT_MULTI_VCARD_URI} to indicate that the returned
         * vcard should not contain a photo.
         *
-        * @hide
+        * This is useful for obtaining a space efficient vcard.
         */
-        public static final String QUERY_PARAMETER_VCARD_NO_PHOTO = "nophoto";
+        public static final String QUERY_PARAMETER_VCARD_NO_PHOTO = "no_photo";
 
         /**
          * Base {@link Uri} for referencing multiple {@link Contacts} entry,
@@ -2194,6 +2194,16 @@
         public static final String CONTACT_ID = "contact_id";
 
         /**
+         * Persistent unique id for each raw_contact within its account.
+         * This id is provided by its own data source, and can be used to backup metadata
+         * to the server.
+         * This should be unique within each set of account_name/account_type/data_set
+         *
+         * @hide
+         */
+        public static final String BACKUP_ID = "backup_id";
+
+        /**
          * The data set within the account that this row belongs to.  This allows
          * multiple sync adapters for the same account type to distinguish between
          * each others' data.
@@ -2238,33 +2248,6 @@
         public static final String DELETED = "deleted";
 
         /**
-         * The "name_verified" flag: "1" means that the name fields on this raw
-         * contact can be trusted and therefore should be used for the entire
-         * aggregated contact.
-         * <p>
-         * If an aggregated contact contains more than one raw contact with a
-         * verified name, one of those verified names is chosen at random.
-         * If an aggregated contact contains no verified names, the
-         * name is chosen randomly from the constituent raw contacts.
-         * </p>
-         * <p>
-         * Updating this flag from "0" to "1" automatically resets it to "0" on
-         * all other raw contacts in the same aggregated contact.
-         * </p>
-         * <p>
-         * Sync adapters should only specify a value for this column when
-         * inserting a raw contact and leave it out when doing an update.
-         * </p>
-         * <p>
-         * The default value is "0"
-         * </p>
-         * <p>Type: INTEGER</p>
-         *
-         * @hide
-         */
-        public static final String NAME_VERIFIED = "name_verified";
-
-        /**
          * The "read-only" flag: "0" by default, "1" if the row cannot be modified or
          * deleted except by a sync adapter.  See {@link ContactsContract#CALLER_IS_SYNCADAPTER}.
          * <P>Type: INTEGER</P>
@@ -2960,7 +2943,6 @@
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED);
-                DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, NAME_VERIFIED);
                 android.content.Entity contact = new android.content.Entity(cv);
 
                 // read data rows until the contact id changes
@@ -3986,6 +3968,13 @@
         public static final String MIMETYPE = "mimetype";
 
         /**
+         * Hash id on the data fields, used for backup and restore.
+         *
+         * @hide
+         */
+        public static final String HASH_ID = "hash_id";
+
+        /**
          * A reference to the {@link RawContacts#_ID}
          * that this data belongs to.
          */
@@ -8072,8 +8061,10 @@
         public static final String EXTRA_TARGET_RECT = "android.provider.extra.TARGET_RECT";
 
         /**
-         * Extra used to specify size of pivot dialog.
-         * @hide
+         * Extra used to specify size of QuickContacts. Not all implementations of QuickContacts
+         * will respect this extra's value.
+         *
+         * One of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or {@link #MODE_LARGE}.
          */
         public static final String EXTRA_MODE = "android.provider.extra.MODE";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e055203..dddbe78 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.app.SearchManager;
 import android.app.WallpaperManager;
 import android.content.ComponentName;
@@ -5104,6 +5105,7 @@
          * Whether Theater Mode is on.
          * {@hide}
          */
+        @SystemApi
         public static final String THEATER_MODE_ON = "theater_mode_on";
 
         /**
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2b53c48..b84c3aa 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1754,8 +1754,8 @@
 
     private char getEllipsisChar(TextUtils.TruncateAt method) {
         return (method == TextUtils.TruncateAt.END_SMALL) ?
-                ELLIPSIS_TWO_DOTS[0] :
-                ELLIPSIS_NORMAL[0];
+                TextUtils.ELLIPSIS_TWO_DOTS[0] :
+                TextUtils.ELLIPSIS_NORMAL[0];
     }
 
     private void ellipsize(int start, int end, int line,
@@ -1952,6 +1952,4 @@
     /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT =
         new Directions(new int[] { 0, RUN_LENGTH_MASK | RUN_RTL_FLAG });
 
-    /* package */ static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..."
-    /* package */ static final char[] ELLIPSIS_TWO_DOTS = { '\u2025' }; // this is ".."
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 5b07397..2d4b4dc 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -554,7 +554,7 @@
 
         float ellipsisWidth = paint.measureText(
                 (where == TextUtils.TruncateAt.END_SMALL) ?
-                        ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL, 0, 1);
+                        TextUtils.ELLIPSIS_TWO_DOTS : TextUtils.ELLIPSIS_NORMAL, 0, 1);
         int ellipsisStart = 0;
         int ellipsisCount = 0;
         int len = lineEnd - lineStart;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 8a8c6d8..48bb5dd 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -63,9 +63,12 @@
 
 public class TextUtils {
     private static final String TAG = "TextUtils";
-    private static final String ELLIPSIS = new String(Layout.ELLIPSIS_NORMAL);
-    private static final String ELLIPSIS_TWO_DOTS = new String(Layout.ELLIPSIS_TWO_DOTS);
 
+    /* package */ static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..."
+    private static final String ELLIPSIS_STRING = new String(ELLIPSIS_NORMAL);
+
+    /* package */ static final char[] ELLIPSIS_TWO_DOTS = { '\u2025' }; // this is ".."
+    private static final String ELLIPSIS_TWO_DOTS_STRING = new String(ELLIPSIS_TWO_DOTS);
 
     private TextUtils() { /* cannot be instantiated */ }
 
@@ -1085,7 +1088,7 @@
                                          EllipsizeCallback callback) {
         return ellipsize(text, paint, avail, where, preserveLength, callback,
                 TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS);
+                (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS_STRING : ELLIPSIS_STRING);
     }
 
     /**
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 7bd6287..80245ef 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -268,7 +268,12 @@
         @Override
         public boolean onPreDraw() {
             removeListeners();
-            sPendingTransitions.remove(mSceneRoot);
+
+            // Don't start the transition if it's no longer pending.
+            if (!sPendingTransitions.remove(mSceneRoot)) {
+                return true;
+            }
+
             // Add to running list, handle end to remove it
             final ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
                     getRunningTransitions();
@@ -417,4 +422,24 @@
             sceneChangeRunTransition(sceneRoot, transitionClone);
         }
     }
+
+    /**
+     * Ends all pending and ongoing transitions on the specified scene root.
+     *
+     * @param sceneRoot The root of the View hierarchy to end transitions on.
+     * @hide
+     */
+    public static void endTransitions(final ViewGroup sceneRoot) {
+        sPendingTransitions.remove(sceneRoot);
+
+        final ArrayList<Transition> runningTransitions = getRunningTransitions().get(sceneRoot);
+        if (runningTransitions != null) {
+            final int count = runningTransitions.size();
+            for (int i = 0; i < count; i++) {
+                final Transition transition = runningTransitions.get(i);
+                transition.end();
+            }
+        }
+
+    }
 }
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 7c9861f..6ed3885 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -255,7 +255,10 @@
     }
 
     private ArrayMap(boolean immutable) {
-        mHashes = EmptyArray.INT;
+        // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
+        // instance instead of the usual EmptyArray.INT. The reference
+        // is checked later to see if the array is allowed to grow.
+        mHashes = immutable ? EMPTY_IMMUTABLE_INTS : EmptyArray.INT;
         mArray = EmptyArray.OBJECT;
         mSize = 0;
     }
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 5e05683..68ad782 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -636,95 +636,6 @@
         }
     }
 
-    public void computeClickPointInScreenClientThread(long accessibilityNodeId,
-            Region interactiveRegion, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
-            long interrogatingTid, MagnificationSpec spec) {
-        Message message = mHandler.obtainMessage();
-        message.what = PrivateHandler.MSG_COMPUTE_CLICK_POINT_IN_SCREEN;
-
-        SomeArgs args = SomeArgs.obtain();
-        args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
-        args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
-        args.argi3 = interactionId;
-        args.arg1 = callback;
-        args.arg2 = spec;
-        args.arg3 = interactiveRegion;
-
-        message.obj = args;
-
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
-    }
-
-    private void computeClickPointInScreenUiThread(Message message) {
-        SomeArgs args = (SomeArgs) message.obj;
-        final int accessibilityViewId = args.argi1;
-        final int virtualDescendantId = args.argi2;
-        final int interactionId = args.argi3;
-        final IAccessibilityInteractionConnectionCallback callback =
-                (IAccessibilityInteractionConnectionCallback) args.arg1;
-        final MagnificationSpec spec = (MagnificationSpec) args.arg2;
-        final Region interactiveRegion = (Region) args.arg3;
-        args.recycle();
-
-        boolean succeeded = false;
-        Point point = mTempPoint;
-        try {
-            if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
-                return;
-            }
-            View target = null;
-            if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                target = findViewByAccessibilityId(accessibilityViewId);
-            } else {
-                target = mViewRootImpl.mView;
-            }
-            if (target != null && isShown(target)) {
-                AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
-                if (provider != null) {
-                    // For virtual views just use the center of the bounds in screen.
-                    AccessibilityNodeInfo node = null;
-                    if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                        node = provider.createAccessibilityNodeInfo(virtualDescendantId);
-                    } else {
-                        node = provider.createAccessibilityNodeInfo(
-                                AccessibilityNodeProvider.HOST_VIEW_ID);
-                    }
-                    if (node != null) {
-                        succeeded = true;
-                        Rect boundsInScreen = mTempRect;
-                        node.getBoundsInScreen(boundsInScreen);
-                        point.set(boundsInScreen.centerX(), boundsInScreen.centerY());
-                    }
-                } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                    // For a real view, ask the view to compute the click point.
-                    succeeded = target.computeClickPointInScreenForAccessibility(
-                            interactiveRegion, point);
-                }
-            }
-        } finally {
-            try {
-                Point result = null;
-                if (succeeded) {
-                    applyAppScaleAndMagnificationSpecIfNeeded(point, spec);
-                    result = point;
-                }
-                callback.setComputeClickPointInScreenActionResult(result, interactionId);
-            } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-            }
-        }
-    }
-
     private View findViewByAccessibilityId(int accessibilityId) {
         View root = mViewRootImpl.mView;
         if (root == null) {
@@ -1201,7 +1112,6 @@
         private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4;
         private final static int MSG_FIND_FOCUS = 5;
         private final static int MSG_FOCUS_SEARCH = 6;
-        private final static int MSG_COMPUTE_CLICK_POINT_IN_SCREEN = 7;
 
         public PrivateHandler(Looper looper) {
             super(looper);
@@ -1223,8 +1133,6 @@
                     return "MSG_FIND_FOCUS";
                 case MSG_FOCUS_SEARCH:
                     return "MSG_FOCUS_SEARCH";
-                case MSG_COMPUTE_CLICK_POINT_IN_SCREEN:
-                    return "MSG_COMPUTE_CLICK_POINT_IN_SCREEN";
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
@@ -1252,9 +1160,6 @@
                 case MSG_FOCUS_SEARCH: {
                     focusSearchUiThread(message);
                 } break;
-                case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: {
-                    computeClickPointInScreenUiThread(message);
-                } break;
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index a359952..ae4b60f 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -29,8 +29,21 @@
  * </div>
  */
 public abstract class ActionMode {
+
+    /**
+     * The action mode is treated as a Primary mode. This is the default.
+     * Use with {@link #setType}.
+     */
+    public static final int TYPE_PRIMARY = 0;
+    /**
+     * The action mode is treated as a Floating Toolbar.
+     * Use with {@link #setType}.
+     */
+    public static final int TYPE_FLOATING = 1;
+
     private Object mTag;
     private boolean mTitleOptionalHint;
+    private int mType = TYPE_PRIMARY;
 
     /**
      * Set a tag object associated with this ActionMode.
@@ -154,6 +167,25 @@
     public abstract void setCustomView(View view);
 
     /**
+     * Set a type for this action mode. This will affect how the system renders the action mode if
+     * it has to.
+     *
+     * @param type One of {@link #TYPE_PRIMARY} or {@link #TYPE_FLOATING}.
+     */
+    public void setType(int type) {
+        mType = type;
+    }
+
+    /**
+     * Returns the type for this action mode.
+     *
+     * @return One of {@link #TYPE_PRIMARY} or {@link #TYPE_FLOATING}.
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
      * Invalidate the action mode and refresh menu content. The mode's
      * {@link ActionMode.Callback} will have its
      * {@link Callback#onPrepareActionMode(ActionMode, Menu)} method called.
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index ac32430..a5225cb 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -16,24 +16,25 @@
 
 package android.view;
 
-import android.annotation.Nullable;
-import android.graphics.Canvas;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Trace;
-import android.util.TypedValue;
-import android.widget.FrameLayout;
+import com.android.internal.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.Canvas;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.util.Xml;
+import android.widget.FrameLayout;
 
 import java.io.IOException;
 import java.lang.reflect.Constructor;
@@ -925,6 +926,14 @@
                                 inheritContext);
                         final ViewGroup group = (ViewGroup) parent;
 
+                        final TypedArray a = context.obtainStyledAttributes(
+                                attrs, R.styleable.Include);
+                        final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
+                        final int visibility = a.getInt(R.styleable.Include_visibility, -1);
+                        final boolean hasWidth = a.hasValue(R.styleable.Include_layout_width);
+                        final boolean hasHeight = a.hasValue(R.styleable.Include_layout_height);
+                        a.recycle();
+
                         // We try to load the layout params set in the <include /> tag. If
                         // they don't exist, we will rely on the layout params set in the
                         // included XML file.
@@ -934,27 +943,21 @@
                         // successfully loaded layout params from the <include /> tag,
                         // false means we need to rely on the included layout params.
                         ViewGroup.LayoutParams params = null;
-                        try {
-                            params = group.generateLayoutParams(attrs);
-                        } catch (RuntimeException e) {
-                            params = group.generateLayoutParams(childAttrs);
-                        } finally {
-                            if (params != null) {
-                                view.setLayoutParams(params);
+                        if (hasWidth && hasHeight) {
+                            try {
+                                params = group.generateLayoutParams(attrs);
+                            } catch (RuntimeException e) {
+                                // Ignore, just fail over to child attrs.
                             }
                         }
+                        if (params == null) {
+                            params = group.generateLayoutParams(childAttrs);
+                        }
+                        view.setLayoutParams(params);
 
                         // Inflate all children.
                         rInflate(childParser, view, childAttrs, true, true);
 
-                        final TypedArray a = context.obtainStyledAttributes(
-                                attrs, com.android.internal.R.styleable.Include);
-                        final int id = a.getResourceId(
-                                com.android.internal.R.styleable.Include_id, View.NO_ID);
-                        final int visibility = a.getInt(
-                                com.android.internal.R.styleable.Include_visibility, -1);
-                        a.recycle();
-
                         if (id != View.NO_ID) {
                             view.setId(id);
                         }
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 1c5c41c..5e45c8f 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -402,6 +402,23 @@
     public static final int FLAG_TAINTED = 0x80000000;
 
     /**
+     * Private flag indicating that this event was synthesized by the system and
+     * should be delivered to the accessibility focused view first. When being
+     * dispatched such an event is not handled by predecessors of the accessibility
+     * focused view and after the event reaches that view the flag is cleared and
+     * normal event dispatch is performed. This ensures that the platform can click
+     * on any view that has accessibility focus which is semantically equivalent to
+     * asking the view to perform a click accessibility action but more generic as
+     * views not implementing click action correctly can still be activated.
+     *
+     * @hide
+     * @see #isTargetAccessibilityFocus()
+     * @see #setTargetAccessibilityFocus(boolean)
+     */
+    public static final int FLAG_TARGET_ACCESSIBILITY_FOCUS = 0x40000000;
+
+
+    /**
      * Flag indicating the motion event intersected the top edge of the screen.
      */
     public static final int EDGE_TOP = 0x00000001;
@@ -1766,6 +1783,20 @@
         nativeSetFlags(mNativePtr, tainted ? flags | FLAG_TAINTED : flags & ~FLAG_TAINTED);
     }
 
+    /** @hide */
+    public final boolean isTargetAccessibilityFocus() {
+        final int flags = getFlags();
+        return (flags & FLAG_TARGET_ACCESSIBILITY_FOCUS) != 0;
+    }
+
+    /** @hide */
+    public final void setTargetAccessibilityFocus(boolean targetsFocus) {
+        final int flags = getFlags();
+        nativeSetFlags(mNativePtr, targetsFocus
+                ? flags | FLAG_TARGET_ACCESSIBILITY_FOCUS
+                : flags & ~FLAG_TARGET_ACCESSIBILITY_FOCUS);
+    }
+
     /**
      * Returns the time (in ms) when the user originally pressed down to start
      * a stream of position events.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 259367e..60a1ca1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2544,6 +2544,20 @@
     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
 
     /**
+     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
+     * is compatible with light status bar backgrounds.
+     *
+     * <p>For this to take effect, the window must request
+     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
+     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
+     *         FLAG_TRANSLUCENT_STATUS}.
+     *
+     * @see android.R.attr#windowHasLightStatusBar
+     */
+    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
+
+    /**
      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
      */
     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
@@ -4676,7 +4690,7 @@
      *
      * @see #setClickable(boolean)
      */
-    public void setOnClickListener(OnClickListener l) {
+    public void setOnClickListener(@Nullable OnClickListener l) {
         if (!isClickable()) {
             setClickable(true);
         }
@@ -4700,7 +4714,7 @@
      *
      * @see #setLongClickable(boolean)
      */
-    public void setOnLongClickListener(OnLongClickListener l) {
+    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
         if (!isLongClickable()) {
             setLongClickable(true);
         }
@@ -5416,7 +5430,7 @@
      */
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         event.setSource(this);
-        event.setClassName(View.class.getName());
+        event.setClassName(getAccessibilityClassName());
         event.setPackageName(getContext().getPackageName());
         event.setEnabled(isEnabled());
         event.setContentDescription(mContentDescription);
@@ -5522,12 +5536,23 @@
     }
 
     /**
-     * Gets the location of this view in screen coordintates.
+     * Gets the location of this view in screen coordinates.
      *
      * @param outRect The output location
      * @hide
      */
     public void getBoundsOnScreen(Rect outRect) {
+        getBoundsOnScreen(outRect, false);
+    }
+
+    /**
+     * Gets the location of this view in screen coordinates.
+     *
+     * @param outRect The output location
+     * @param clipToParent Whether to clip child bounds to the parent ones.
+     * @hide
+     */
+    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
         if (mAttachInfo == null) {
             return;
         }
@@ -5547,6 +5572,13 @@
 
             position.offset(-parentView.mScrollX, -parentView.mScrollY);
 
+            if (clipToParent) {
+                position.left = Math.max(position.left, 0);
+                position.top = Math.max(position.top, 0);
+                position.right = Math.min(position.right, parentView.getWidth());
+                position.bottom = Math.min(position.bottom, parentView.getHeight());
+            }
+
             if (!parentView.hasIdentityMatrix()) {
                 parentView.getMatrix().mapRect(position);
             }
@@ -5568,6 +5600,26 @@
     }
 
     /**
+     * Return the class name of this object to be used for accessibility purposes.
+     * Subclasses should only override this if they are implementing something that
+     * should be seen as a completely new class of view when used by accessibility,
+     * unrelated to the class it is deriving from.  This is used to fill in
+     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
+     */
+    public CharSequence getAccessibilityClassName() {
+        return View.class.getName();
+    }
+
+    /**
+     * Called when assist data is being retrieved from a view as part of
+     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
+     * @param data
+     * @param extras
+     */
+    public void onProvideAssistData(ViewAssistData data, Bundle extras) {
+    }
+
+    /**
      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
      *
      * Note: Called from the default {@link AccessibilityDelegate}.
@@ -5580,7 +5632,7 @@
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
-        getBoundsOnScreen(bounds);
+        getBoundsOnScreen(bounds, true);
         info.setBoundsInScreen(bounds);
 
         ViewParent parent = getParentForAccessibility();
@@ -5649,7 +5701,7 @@
         info.setVisibleToUser(isVisibleToUser());
 
         info.setPackageName(mContext.getPackageName());
-        info.setClassName(View.class.getName());
+        info.setClassName(getAccessibilityClassName());
         info.setContentDescription(getContentDescription());
 
         info.setEnabled(isEnabled());
@@ -5776,142 +5828,6 @@
     }
 
     /**
-     * Computes a point on which a sequence of a down/up event can be sent to
-     * trigger clicking this view. This method is for the exclusive use by the
-     * accessibility layer to determine where to send a click event in explore
-     * by touch mode.
-     *
-     * @param interactiveRegion The interactive portion of this window.
-     * @param outPoint The point to populate.
-     * @return True of such a point exists.
-     */
-    boolean computeClickPointInScreenForAccessibility(Region interactiveRegion,
-            Point outPoint) {
-        // Since the interactive portion of the view is a region but as a view
-        // may have a transformation matrix which cannot be applied to a
-        // region we compute the view bounds rectangle and all interactive
-        // predecessor's and sibling's (siblings of predecessors included)
-        // rectangles that intersect the view bounds. At the
-        // end if the view was partially covered by another interactive
-        // view we compute the view's interactive region and pick a point
-        // on its boundary path as regions do not offer APIs to get inner
-        // points. Note that the the code is optimized to fail early and
-        // avoid unnecessary allocations plus computations.
-
-        // The current approach has edge cases that may produce false
-        // positives or false negatives. For example, a portion of the
-        // view may be covered by an interactive descendant of a
-        // predecessor, which we do not compute. Also a view may be handling
-        // raw touch events instead registering click listeners, which
-        // we cannot compute. Despite these limitations this approach will
-        // work most of the time and it is a huge improvement over just
-        // blindly sending the down and up events in the center of the
-        // view.
-
-        // Cannot click on an unattached view.
-        if (mAttachInfo == null) {
-            return false;
-        }
-
-        // Attached to an invisible window means this view is not visible.
-        if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
-            return false;
-        }
-
-        RectF bounds = mAttachInfo.mTmpTransformRect;
-        bounds.set(0, 0, getWidth(), getHeight());
-        List<RectF> intersections = mAttachInfo.mTmpRectList;
-        intersections.clear();
-
-        if (mParent instanceof ViewGroup) {
-            ViewGroup parentGroup = (ViewGroup) mParent;
-            if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
-                    this, bounds, intersections)) {
-                intersections.clear();
-                return false;
-            }
-        }
-
-        // Take into account the window location.
-        final int dx = mAttachInfo.mWindowLeft;
-        final int dy = mAttachInfo.mWindowTop;
-        bounds.offset(dx, dy);
-        offsetRects(intersections, dx, dy);
-
-        if (intersections.isEmpty() && interactiveRegion == null) {
-            outPoint.set((int) bounds.centerX(), (int) bounds.centerY());
-        } else {
-            // This view is partially covered by other views, then compute
-            // the not covered region and pick a point on its boundary.
-            Region region = new Region();
-            region.set((int) bounds.left, (int) bounds.top,
-                    (int) bounds.right, (int) bounds.bottom);
-
-            final int intersectionCount = intersections.size();
-            for (int i = intersectionCount - 1; i >= 0; i--) {
-                RectF intersection = intersections.remove(i);
-                region.op((int) intersection.left, (int) intersection.top,
-                        (int) intersection.right, (int) intersection.bottom,
-                        Region.Op.DIFFERENCE);
-            }
-
-            // If the view is completely covered, done.
-            if (region.isEmpty()) {
-                return false;
-            }
-
-            // Take into account the interactive portion of the window
-            // as the rest is covered by other windows. If no such a region
-            // then the whole window is interactive.
-            if (interactiveRegion != null) {
-                region.op(interactiveRegion, Region.Op.INTERSECT);
-            }
-
-            // Take into account the window bounds.
-            final View root = getRootView();
-            if (root != null) {
-                region.op(dx, dy, root.getWidth() + dx, root.getHeight() + dy, Region.Op.INTERSECT);
-            }
-
-            // If the view is completely covered, done.
-            if (region.isEmpty()) {
-                return false;
-            }
-
-            // Try a shortcut here.
-            if (region.isRect()) {
-                Rect regionBounds = mAttachInfo.mTmpInvalRect;
-                region.getBounds(regionBounds);
-                outPoint.set(regionBounds.centerX(), regionBounds.centerY());
-                return true;
-            }
-
-            // Get the a point on the region boundary path.
-            Path path = region.getBoundaryPath();
-            PathMeasure pathMeasure = new PathMeasure(path, false);
-            final float[] coordinates = mAttachInfo.mTmpTransformLocation;
-
-            // Without loss of generality pick a point.
-            final float point = pathMeasure.getLength() * 0.01f;
-            if (!pathMeasure.getPosTan(point, coordinates, null)) {
-                return false;
-            }
-
-            outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1]));
-        }
-
-        return true;
-    }
-
-    static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
-        final int rectCount = rects.size();
-        for (int i = 0; i < rectCount; i++) {
-            RectF intersection = rects.get(i);
-            intersection.offset(offsetX, offsetY);
-        }
-    }
-
-    /**
      * Returns the delegate for implementing accessibility support via
      * composition. For more details see {@link AccessibilityDelegate}.
      *
@@ -6780,7 +6696,6 @@
     @RemotableViewMethod
     public void setVisibility(@Visibility int visibility) {
         setFlags(visibility, VISIBILITY_MASK);
-        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
     }
 
     /**
@@ -8526,6 +8441,17 @@
      * @return True if the event was handled by the view, false otherwise.
      */
     public boolean dispatchTouchEvent(MotionEvent event) {
+        // If the event should be handled by accessibility focus first.
+        if (event.isTargetAccessibilityFocus()) {
+            // We don't have focus or no virtual descendant has it, do not handle the event.
+            if (!isAccessibilityFocused() && !(getViewRootImpl() != null && getViewRootImpl()
+                    .getAccessibilityFocusedHost() == this)) {
+                return false;
+            }
+            // We have focus and got the event, then use normal event dispatch.
+            event.setTargetAccessibilityFocus(false);
+        }
+
         boolean result = false;
 
         if (mInputEventConsistencyVerifier != null) {
@@ -8806,20 +8732,28 @@
     }
 
     /**
-     * Called when the visibility of the view or an ancestor of the view is changed.
-     * @param changedView The view whose visibility changed. Could be 'this' or
-     * an ancestor view.
-     * @param visibility The new visibility of changedView: {@link #VISIBLE},
-     * {@link #INVISIBLE} or {@link #GONE}.
+     * Called when the visibility of the view or an ancestor of the view has
+     * changed.
+     *
+     * @param changedView The view whose visibility changed. May be
+     *                    {@code this} or an ancestor view.
+     * @param visibility The new visibility, one of {@link #VISIBLE},
+     *                   {@link #INVISIBLE} or {@link #GONE}.
      */
     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
-        if (visibility == VISIBLE) {
+        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
+        if (visible) {
             if (mAttachInfo != null) {
                 initialAwakenScrollBars();
             } else {
                 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
             }
         }
+
+        final Drawable dr = mBackground;
+        if (dr != null && visible != dr.isVisible()) {
+            dr.setVisible(visible, false);
+        }
     }
 
     /**
@@ -12958,7 +12892,7 @@
                         Interpolator.Result.FREEZE_END) {
                     cache.state = ScrollabilityCache.OFF;
                 } else {
-                    cache.scrollBar.setAlpha(Math.round(values[0]));
+                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
                 }
 
                 // This will make the scroll bars inval themselves after
@@ -12968,7 +12902,7 @@
             } else {
                 // We're just on -- but we may have been fading before so
                 // reset alpha
-                cache.scrollBar.setAlpha(255);
+                cache.scrollBar.mutate().setAlpha(255);
             }
 
 
@@ -14885,10 +14819,9 @@
     void setDisplayListProperties(RenderNode renderNode) {
         if (renderNode != null) {
             renderNode.setHasOverlappingRendering(hasOverlappingRendering());
-            if (mParent instanceof ViewGroup) {
-                renderNode.setClipToBounds(
-                        (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
-            }
+            renderNode.setClipToBounds(mParent instanceof ViewGroup
+                    && ((ViewGroup) mParent).getClipChildren());
+
             float alpha = 1;
             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
diff --git a/core/java/android/view/ViewAssistData.java b/core/java/android/view/ViewAssistData.java
new file mode 100644
index 0000000..74436ea
--- /dev/null
+++ b/core/java/android/view/ViewAssistData.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * Container for storing data generated by {@link View#onProvideAssistData
+ * View.onProvideAssistData}.
+ */
+public abstract class ViewAssistData {
+    public abstract void setText(CharSequence text);
+    public abstract void setText(CharSequence text, int selectionStart, int selectionEnd);
+    public abstract void setHint(CharSequence hint);
+
+    public abstract CharSequence getText();
+    public abstract int getTextSelectionStart();
+    public abstract int getTextSelectionEnd();
+    public abstract CharSequence getHint();
+}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 49e4efa..879fe1965 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -474,9 +474,6 @@
     @ViewDebug.ExportedProperty(category = "layout")
     private int mChildCountWithTransientState = 0;
 
-    // Iterator over the children in decreasing Z order (top children first).
-    private OrderedChildIterator mOrderedChildIterator;
-
     /**
      * Currently registered axes for nested scrolling. Flag set consisting of
      * {@link #SCROLL_AXIS_HORIZONTAL} {@link #SCROLL_AXIS_VERTICAL} or {@link #SCROLL_AXIS_NONE}
@@ -782,144 +779,6 @@
     }
 
     /**
-     * Translates the given bounds and intersections from child coordinates to
-     * local coordinates. In case any interactive sibling of the calling child
-     * covers the latter, a new intersections is added to the intersection list.
-     * This method is for the exclusive use by the accessibility layer to compute
-     * a point where a sequence of down and up events would click on a view.
-     *
-     * @param child The child making the call.
-     * @param bounds The bounds to translate in child coordinates.
-     * @param intersections The intersections of interactive views covering the child.
-     * @return True if the bounds and intersections were computed, false otherwise.
-     */
-    boolean translateBoundsAndIntersectionsInWindowCoordinates(View child,
-            RectF bounds, List<RectF> intersections) {
-        // Not attached, done.
-        if (mAttachInfo == null) {
-            return false;
-        }
-
-        if (getAlpha() <= 0 || getTransitionAlpha() <= 0 ||
-                getVisibility() != VISIBLE) {
-            // Cannot click on a view with an invisible predecessor.
-            return false;
-        }
-
-        // Compensate for the child transformation.
-        if (!child.hasIdentityMatrix()) {
-            Matrix matrix = child.getMatrix();
-            matrix.mapRect(bounds);
-            final int intersectionCount = intersections.size();
-            for (int i = 0; i < intersectionCount; i++) {
-                RectF intersection = intersections.get(i);
-                matrix.mapRect(intersection);
-            }
-        }
-
-        // Translate the bounds from child to parent coordinates.
-        final int dx = child.mLeft - mScrollX;
-        final int dy = child.mTop - mScrollY;
-        bounds.offset(dx, dy);
-        offsetRects(intersections, dx, dy);
-
-        // If the bounds do not intersect our bounds, done.
-        if (!bounds.intersects(0, 0, getWidth(), getHeight())) {
-            return false;
-        }
-
-        // Clip the bounds by our bounds.
-        bounds.left = Math.max(bounds.left, 0);
-        bounds.top = Math.max(bounds.top, 0);
-        bounds.right = Math.min(bounds.right, getWidth());
-        bounds.bottom = Math.min(bounds.bottom, getHeight());
-
-        Iterator<View> iterator = obtainOrderedChildIterator();
-        while (iterator.hasNext()) {
-            View sibling = iterator.next();
-
-            // We care only about siblings over the child.
-            if (sibling == child) {
-                break;
-            }
-
-            // Ignore invisible views as they are not interactive.
-            if (!isVisible(sibling)) {
-                continue;
-            }
-
-            // Compute the sibling bounds in its coordinates.
-            RectF siblingBounds = mAttachInfo.mTmpTransformRect1;
-            siblingBounds.set(0, 0, sibling.getWidth(), sibling.getHeight());
-
-            // Translate the sibling bounds to our coordinates.
-            offsetChildRectToMyCoords(siblingBounds, sibling);
-
-            // Compute the intersection between the child and the sibling.
-            if (siblingBounds.intersect(bounds)) {
-                // Conservatively we consider an overlapping sibling to be
-                // interactive and ignore it. This is not ideal as if the
-                // sibling completely covers the view despite handling no
-                // touch events we will not be able to click on the view.
-                intersections.add(siblingBounds);
-            }
-        }
-
-        releaseOrderedChildIterator();
-
-        if (mParent instanceof ViewGroup) {
-            ViewGroup parentGroup = (ViewGroup) mParent;
-            return parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
-                    this, bounds, intersections);
-        }
-
-        return true;
-    }
-
-    private void offsetChildRectToMyCoords(RectF rect, View child) {
-        if (!child.hasIdentityMatrix()) {
-            child.getMatrix().mapRect(rect);
-        }
-        final int childDx = child.mLeft - mScrollX;
-        final int childDy = child.mTop - mScrollY;
-        rect.offset(childDx, childDy);
-    }
-
-    private static boolean isVisible(View view) {
-        return (view.getAlpha() > 0 && view.getTransitionAlpha() > 0 &&
-                view.getVisibility() == VISIBLE);
-    }
-
-    /**
-     * Obtains the iterator to traverse the children in a descending Z order.
-     * Only one party can use the iterator at any given time and you cannot
-     * modify the children while using this iterator. Acquisition if already
-     * obtained is an error.
-     *
-     * @return The child iterator.
-     */
-    OrderedChildIterator obtainOrderedChildIterator() {
-        if (mOrderedChildIterator == null) {
-            mOrderedChildIterator = new OrderedChildIterator();
-        } else if (mOrderedChildIterator.isInitialized()) {
-            throw new IllegalStateException("Already obtained");
-        }
-        mOrderedChildIterator.initialize();
-        return mOrderedChildIterator;
-    }
-
-    /**
-     * Releases the iterator to traverse the children in a descending Z order.
-     * Release if not obtained is an error.
-     */
-    void releaseOrderedChildIterator() {
-        if (mOrderedChildIterator == null || !mOrderedChildIterator.isInitialized()) {
-            throw new IllegalStateException("Not obtained");
-        }
-        mOrderedChildIterator.release();
-    }
-
-    /**
      * Called when a child view has changed whether or not it is tracking transient state.
      */
     public void childHasTransientStateChanged(View child, boolean childHasTransientState) {
@@ -2074,6 +1933,9 @@
             mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
         }
 
+        // Whether this event should be handled by the accessibility focus first.
+        final boolean targetAccessibilityFocus = ev.isTargetAccessibilityFocus();
+
         boolean handled = false;
         if (onFilterTouchEventForSecurity(ev)) {
             final int action = ev.getAction();
@@ -2090,19 +1952,24 @@
 
             // Check for interception.
             final boolean intercepted;
-            if (actionMasked == MotionEvent.ACTION_DOWN
-                    || mFirstTouchTarget != null) {
-                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
-                if (!disallowIntercept) {
-                    intercepted = onInterceptTouchEvent(ev);
-                    ev.setAction(action); // restore action in case it was changed
+            if (!targetAccessibilityFocus) {
+                if (actionMasked == MotionEvent.ACTION_DOWN
+                        || mFirstTouchTarget != null) {
+                    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
+                    if (!disallowIntercept) {
+                        intercepted = onInterceptTouchEvent(ev);
+                        ev.setAction(action); // restore action in case it was changed
+                    } else {
+                        intercepted = false;
+                    }
                 } else {
-                    intercepted = false;
+                    // There are no touch targets and this action is not an initial down
+                    // so this view group continues to intercept touches.
+                    intercepted = true;
                 }
             } else {
-                // There are no touch targets and this action is not an initial down
-                // so this view group continues to intercept touches.
-                intercepted = true;
+                // If event should reach the accessibility focus first, do not intercept it.
+                intercepted = false;
             }
 
             // Check for cancelation.
@@ -2116,7 +1983,8 @@
             if (!canceled && !intercepted) {
                 if (actionMasked == MotionEvent.ACTION_DOWN
                         || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
-                        || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
+                        || actionMasked == MotionEvent.ACTION_HOVER_MOVE
+                        || targetAccessibilityFocus) {
                     final int actionIndex = ev.getActionIndex(); // always 0 for down
                     final int idBitsToAssign = split ? 1 << ev.getPointerId(actionIndex)
                             : TouchTarget.ALL_POINTER_IDS;
@@ -7408,57 +7276,4 @@
 
         canvas.drawLines(sDebugLines, paint);
     }
-
-    private final class OrderedChildIterator implements Iterator<View> {
-        private List<View> mOrderedChildList;
-        private boolean mUseCustomOrder;
-        private int mCurrentIndex;
-        private boolean mInitialized;
-
-        public void initialize() {
-            mOrderedChildList = buildOrderedChildList();
-            mUseCustomOrder = (mOrderedChildList == null)
-                    && isChildrenDrawingOrderEnabled();
-            mCurrentIndex = mChildrenCount - 1;
-            mInitialized = true;
-        }
-
-        public void release() {
-            if (mOrderedChildList != null) {
-                mOrderedChildList.clear();
-            }
-            mUseCustomOrder = false;
-            mCurrentIndex = 0;
-            mInitialized = false;
-        }
-
-        public boolean isInitialized() {
-            return mInitialized;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return (mCurrentIndex >= 0);
-        }
-
-        @Override
-        public View next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException("No such element");
-            }
-            return getChild(mCurrentIndex--);
-        }
-
-        private View getChild(int index) {
-            final int childIndex = mUseCustomOrder
-                    ? getChildDrawingOrder(mChildrenCount, index) : index;
-            return (mOrderedChildList == null)
-                    ? mChildren[childIndex] : mOrderedChildList.get(childIndex);
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 151ff83..570cb72 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -472,8 +472,10 @@
 
                 // Compute surface insets required to draw at specified Z value.
                 // TODO: Use real shadow insets for a constant max Z.
-                final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
-                attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+                if (!attrs.hasManualSurfaceInsets) {
+                    final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
+                    attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+                }
 
                 CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
                 mTranslator = compatibilityInfo.getTranslator();
@@ -649,6 +651,10 @@
         return (mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
     }
 
+    public CharSequence getTitle() {
+        return mWindowAttributes.getTitle();
+    }
+
     void destroyHardwareResources() {
         if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
@@ -760,6 +766,7 @@
             final int oldInsetRight = mWindowAttributes.surfaceInsets.right;
             final int oldInsetBottom = mWindowAttributes.surfaceInsets.bottom;
             final int oldSoftInputMode = mWindowAttributes.softInputMode;
+            final boolean oldHasManualSurfaceInsets = mWindowAttributes.hasManualSurfaceInsets;
 
             // Keep track of the actual window flags supplied by the client.
             mClientWindowLayoutFlags = attrs.flags;
@@ -786,6 +793,7 @@
             // Restore old surface insets.
             mWindowAttributes.surfaceInsets.set(
                     oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
+            mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
 
             applyKeepScreenOnFlag(mWindowAttributes);
 
@@ -2708,7 +2716,7 @@
 
         final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
         if (provider == null) {
-            host.getBoundsOnScreen(bounds);
+            host.getBoundsOnScreen(bounds, true);
         } else if (mAccessibilityFocusedVirtualView != null) {
             mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
         } else {
@@ -6840,26 +6848,6 @@
         }
 
         @Override
-        public void computeClickPointInScreen(long accessibilityNodeId, Region interactiveRegion,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback,
-                int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
-            ViewRootImpl viewRootImpl = mViewRootImpl.get();
-            if (viewRootImpl != null && viewRootImpl.mView != null) {
-                viewRootImpl.getAccessibilityInteractionController()
-                        .computeClickPointInScreenClientThread(accessibilityNodeId,
-                                interactiveRegion, interactionId, callback, interrogatingPid,
-                                interrogatingTid, spec);
-            } else {
-                // We cannot make the call and notify the caller so it does not wait.
-                try {
-                    callback.setComputeClickPointInScreenActionResult(null, interactionId);
-                } catch (RemoteException re) {
-                    /* best effort - ignore */
-                }
-            }
-        }
-
-        @Override
         public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
                 String viewId, Region interactiveRegion, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 3f2f3a5..8704356 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -102,10 +102,12 @@
      */
     public static final int FEATURE_SWIPE_TO_DISMISS = 11;
     /**
-     * Flag for requesting that window content changes should be represented
-     * with scenes and transitions.
+     * Flag for requesting that window content changes should be animated using a
+     * TransitionManager.
      *
-     * TODO Add docs
+     * <p>The TransitionManager is set using
+     * {@link #setTransitionManager(android.transition.TransitionManager)}. If none is set,
+     * a default TransitionManager will be used.</p>
      *
      * @see #setContentView
      */
@@ -1019,10 +1021,16 @@
      * <p>Note that calling this function "locks in" various characteristics
      * of the window that can not, from this point forward, be changed: the
      * features that have been requested with {@link #requestFeature(int)},
-     * and certain window flags as described in {@link #setFlags(int, int)}.
+     * and certain window flags as described in {@link #setFlags(int, int)}.</p>
+     *
+     * <p>If {@link #FEATURE_CONTENT_TRANSITIONS} is set, the window's
+     * TransitionManager will be used to animate content from the current
+     * content View to view.</p>
      *
      * @param view The desired content to display.
      * @param params Layout parameters for the view.
+     * @see #getTransitionManager()
+     * @see #setTransitionManager(android.transition.TransitionManager)
      */
     public abstract void setContentView(View view, ViewGroup.LayoutParams params);
 
@@ -1467,6 +1475,7 @@
      * {@link #setContentView}) if {@link #FEATURE_CONTENT_TRANSITIONS} has been granted.</p>
      *
      * @return This window's content TransitionManager or null if none is set.
+     * @attr ref android.R.styleable#Window_windowContentTransitionManager
      */
     public TransitionManager getTransitionManager() {
         return null;
@@ -1477,6 +1486,7 @@
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
      *
      * @param tm The TransitionManager to use for scene changes.
+     * @attr ref android.R.styleable#Window_windowContentTransitionManager
      */
     public void setTransitionManager(TransitionManager tm) {
         throw new UnsupportedOperationException();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 12b310f..905d6d7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.SystemApi;
 import android.app.Presentation;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -1325,6 +1326,16 @@
          * @hide
          */
         public final Rect surfaceInsets = new Rect();
+
+        /**
+         * Whether the surface insets have been manually set. When set to
+         * {@code false}, the view root will automatically determine the
+         * appropriate surface insets.
+         *
+         * @see #surfaceInsets
+         * @hide
+         */
+        public boolean hasManualSurfaceInsets;
     
         /**
          * The desired bitmap format.  May be one of the constants in
@@ -1583,7 +1594,19 @@
         public final CharSequence getTitle() {
             return mTitle;
         }
-    
+
+        /** @hide */
+        @SystemApi
+        public final void setUserActivityTimeout(long timeout) {
+            userActivityTimeout = timeout;
+        }
+
+        /** @hide */
+        @SystemApi
+        public final long getUserActivityTimeout() {
+            return userActivityTimeout;
+        }
+
         public int describeContents() {
             return 0;
         }
@@ -1621,6 +1644,7 @@
             out.writeInt(surfaceInsets.top);
             out.writeInt(surfaceInsets.right);
             out.writeInt(surfaceInsets.bottom);
+            out.writeInt(hasManualSurfaceInsets ? 1 : 0);
             out.writeInt(needsMenuKey);
         }
 
@@ -1669,6 +1693,7 @@
             surfaceInsets.top = in.readInt();
             surfaceInsets.right = in.readInt();
             surfaceInsets.bottom = in.readInt();
+            hasManualSurfaceInsets = in.readInt() != 0;
             needsMenuKey = in.readInt();
         }
 
@@ -1851,6 +1876,11 @@
                 changes |= SURFACE_INSETS_CHANGED;
             }
 
+            if (hasManualSurfaceInsets != o.hasManualSurfaceInsets) {
+                hasManualSurfaceInsets = o.hasManualSurfaceInsets;
+                changes |= SURFACE_INSETS_CHANGED;
+            }
+
             if (needsMenuKey != o.needsMenuKey) {
                 needsMenuKey = o.needsMenuKey;
                 changes |= NEEDS_MENU_KEY_CHANGED;
@@ -1959,8 +1989,11 @@
             if (userActivityTimeout >= 0) {
                 sb.append(" userActivityTimeout=").append(userActivityTimeout);
             }
-            if (!surfaceInsets.equals(Insets.NONE)) {
+            if (!surfaceInsets.equals(Insets.NONE) || hasManualSurfaceInsets) {
                 sb.append(" surfaceInsets=").append(surfaceInsets);
+                if (hasManualSurfaceInsets) {
+                    sb.append(" (manual)");
+                }
             }
             if (needsMenuKey != NEEDS_MENU_UNSET) {
                 sb.append(" needsMenuKey=");
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index ed17e3f..279627a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -190,6 +190,39 @@
         }
     }
 
+    public ArrayList<ViewRootImpl> getRootViews(IBinder token) {
+        ArrayList<ViewRootImpl> views = new ArrayList<>();
+        synchronized (mLock) {
+            final int numRoots = mRoots.size();
+            for (int i = 0; i < numRoots; ++i) {
+                WindowManager.LayoutParams params = mParams.get(i);
+                if (params.token == null) {
+                    continue;
+                }
+                if (params.token != token) {
+                    boolean isChild = false;
+                    if (params.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
+                            && params.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+                        for (int j = 0 ; j < numRoots; ++j) {
+                            View viewj = mViews.get(j);
+                            WindowManager.LayoutParams paramsj = mParams.get(j);
+                            if (params.token == viewj.getWindowToken()
+                                    && paramsj.token == token) {
+                                isChild = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (!isChild) {
+                        continue;
+                    }
+                }
+                views.add(mRoots.get(i));
+            }
+        }
+        return views;
+    }
+
     public View getRootView(String name) {
         synchronized (mLock) {
             for (int i = mRoots.size() - 1; i >= 0; --i) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 374f7e0..cefd34d 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -99,8 +99,6 @@
 
     private boolean mPerformAccessibilityActionResult;
 
-    private Point mComputeClickPointResult;
-
     private Message mSameThreadMessage;
 
     private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
@@ -522,43 +520,6 @@
         return false;
     }
 
-    /**
-     * Computes a point in screen coordinates where sending a down/up events would
-     * perform a click on an {@link AccessibilityNodeInfo}.
-     *
-     * @param connectionId The id of a connection for interacting with the system.
-     * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
-     *     to query the currently active window.
-     * @param accessibilityNodeId A unique view id or virtual descendant id from
-     *     where to start the search. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
-     *     to start from the root.
-     * @return Point the click point of null if no such point.
-     */
-    public Point computeClickPointInScreen(int connectionId, int accessibilityWindowId,
-            long accessibilityNodeId) {
-        try {
-            IAccessibilityServiceConnection connection = getConnection(connectionId);
-            if (connection != null) {
-                final int interactionId = mInteractionIdCounter.getAndIncrement();
-                final boolean success = connection.computeClickPointInScreen(
-                        accessibilityWindowId, accessibilityNodeId,
-                        interactionId, this, Thread.currentThread().getId());
-                if (success) {
-                    return getComputeClickPointInScreenResultAndClear(interactionId);
-                }
-            } else {
-                if (DEBUG) {
-                    Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
-                }
-            }
-        } catch (RemoteException re) {
-            Log.w(LOG_TAG, "Error while calling remote computeClickPointInScreen", re);
-        }
-        return null;
-    }
-
     public void clearCache() {
         sAccessibilityCache.clear();
     }
@@ -674,34 +635,6 @@
     }
 
     /**
-     * Gets the result of a request to compute a point in screen for clicking on a node.
-     *
-     * @param interactionId The interaction id to match the result with the request.
-     * @return The point or null if no such point.
-     */
-    private Point getComputeClickPointInScreenResultAndClear(int interactionId) {
-        synchronized (mInstanceLock) {
-            final boolean success = waitForResultTimedLocked(interactionId);
-            Point result = success ? mComputeClickPointResult : null;
-            clearResultLocked();
-            return result;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setComputeClickPointInScreenActionResult(Point point, int interactionId) {
-        synchronized (mInstanceLock) {
-            if (interactionId > mInteractionId) {
-                mComputeClickPointResult = point;
-                mInteractionId = interactionId;
-            }
-            mInstanceLock.notifyAll();
-        }
-    }
-
-    /**
      * Clears the result state.
      */
     private void clearResultLocked() {
@@ -709,7 +642,6 @@
         mFindAccessibilityNodeInfoResult = null;
         mFindAccessibilityNodeInfosResult = null;
         mPerformAccessibilityActionResult = false;
-        mComputeClickPointResult = null;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 66a3f46..cecc4af 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -54,8 +54,4 @@
     void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
         int interrogatingPid, long interrogatingTid);
-
-    void computeClickPointInScreen(long accessibilityNodeId, in Region bounds, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
-        long interrogatingTid, in MagnificationSpec spec);
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index f480216..42ae1b3 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -52,12 +52,4 @@
      * @param interactionId The interaction id to match the result with the request.
      */
     void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
-
-    /**
-     * Sets the result of a request to compute a point for clicking in a view.
-     *
-     * @param point The point of null if no such point.
-     * @param interactionId The interaction id to match the result with the request.
-     */
-    void setComputeClickPointInScreenActionResult(in Point point, int interactionId);
 }
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
index 2185658de3..07402b3 100644
--- a/core/java/android/webkit/WebResourceRequest.java
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -42,6 +42,8 @@
 
     /**
      * Gets whether a gesture (such as a click) was associated with the request.
+     * For security reasons in certain situations this method may return false even though the
+     * sequence of events which caused the request to be created was initiated by a user gesture.
      *
      * @return whether a gesture was associated with the request.
      */
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4a7cc6d..01a506c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2387,11 +2387,14 @@
         return mProvider.getViewDelegate().shouldDelayChildPressedState();
     }
 
+    public CharSequence getAccessibilityClassName() {
+        return WebView.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(WebView.class.getName());
         mProvider.getViewDelegate().onInitializeAccessibilityNodeInfo(info);
     }
 
@@ -2399,7 +2402,6 @@
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(WebView.class.getName());
         mProvider.getViewDelegate().onInitializeAccessibilityEvent(event);
     }
 
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index d52dd60..1cc899d 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -50,7 +50,9 @@
      * is called once for each main frame load so a page with iframes or
      * framesets will call onPageStarted one time for the main frame. This also
      * means that onPageStarted will not be called when the contents of an
-     * embedded frame changes, i.e. clicking a link whose target is an iframe.
+     * embedded frame changes, i.e. clicking a link whose target is an iframe,
+     * it will also not be called for fragment navigations (navigations to
+     * #fragment_id).
      *
      * @param view The WebView that is initiating the callback.
      * @param url The url to be loaded.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 7ea3265..e87a117 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -578,6 +578,12 @@
     private boolean mIsChildViewEnabled;
 
     /**
+     * The cached drawable state for the selector. Accounts for child enabled
+     * state, but otherwise identical to the view's own drawable state.
+     */
+    private int[] mSelectorState;
+
+    /**
      * The last scroll state reported to clients through {@link OnScrollListener}.
      */
     private int mLastScrollState = OnScrollListener.SCROLL_STATE_IDLE;
@@ -1486,18 +1492,15 @@
         super.sendAccessibilityEventInternal(eventType);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(AbsListView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return AbsListView.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(AbsListView.class.getName());
         if (isEnabled()) {
             if (canScrollUp()) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
@@ -2789,7 +2792,7 @@
     void updateSelectorState() {
         if (mSelector != null) {
             if (shouldShowSelector()) {
-                mSelector.setState(getDrawableState());
+                mSelector.setState(getDrawableStateForSelector());
             } else {
                 mSelector.setState(StateSet.NOTHING);
             }
@@ -2802,12 +2805,11 @@
         updateSelectorState();
     }
 
-    @Override
-    protected int[] onCreateDrawableState(int extraSpace) {
+    private int[] getDrawableStateForSelector() {
         // If the child view is enabled then do the default behavior.
         if (mIsChildViewEnabled) {
             // Common case
-            return super.onCreateDrawableState(extraSpace);
+            return super.getDrawableState();
         }
 
         // The selector uses this View's drawable state. The selected child view
@@ -2815,10 +2817,12 @@
         // states.
         final int enabledState = ENABLED_STATE_SET[0];
 
-        // If we don't have any extra space, it will return one of the static state arrays,
-        // and clearing the enabled state on those arrays is a bad thing!  If we specify
-        // we need extra space, it will create+copy into a new array that safely mutable.
-        int[] state = super.onCreateDrawableState(extraSpace + 1);
+        // If we don't have any extra space, it will return one of the static
+        // state arrays, and clearing the enabled state on those arrays is a
+        // bad thing! If we specify we need extra space, it will create+copy
+        // into a new array that is safely mutable.
+        final int[] state = onCreateDrawableState(1);
+
         int enabledPos = -1;
         for (int i = state.length - 1; i >= 0; i--) {
             if (state[i] == enabledState) {
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 1f7be63..4f6ea23 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -715,18 +715,15 @@
         return super.onKeyDown(keyCode, event);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(AbsSeekBar.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return AbsSeekBar.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(AbsSeekBar.class.getName());
 
         if (isEnabled()) {
             final int progress = getProgress();
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index 5d8d48fd..e432747 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -470,17 +470,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(AbsSpinner.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(AbsSpinner.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return AbsSpinner.class.getName();
     }
 }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 428b6ce..9b977fa 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -955,11 +955,15 @@
         return false;
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return AdapterView.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(AdapterView.class.getName());
         info.setScrollable(isScrollableForAccessibility());
         View selectedView = getSelectedView();
         if (selectedView != null) {
@@ -971,7 +975,6 @@
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(AdapterView.class.getName());
         event.setScrollable(isScrollableForAccessibility());
         View selectedView = getSelectedView();
         if (selectedView != null) {
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 96eb0e2..a242175 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -1084,17 +1084,8 @@
     public void fyiWillBeAdvancedByHostKThx() {
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(AdapterViewAnimator.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(AdapterViewAnimator.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return AdapterViewAnimator.class.getName();
     }
 }
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index a7ba617..01b6530e 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -304,17 +304,8 @@
         updateRunning(false);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(AdapterViewFlipper.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(AdapterViewFlipper.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return AdapterViewFlipper.class.getName();
     }
 }
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 90d77f9..9b0d0dd 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -111,17 +111,8 @@
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(Button.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(Button.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return Button.class.getName();
     }
 }
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index d58da8f..5e43916 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -501,16 +501,9 @@
         mDelegate.onConfigurationChanged(newConfig);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        event.setClassName(CalendarView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        info.setClassName(CalendarView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return CalendarView.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index b1fb338..5a7d585 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -72,17 +72,8 @@
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(CheckBox.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(CheckBox.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return CheckBox.class.getName();
     }
 }
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 477862b..344d00a 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -435,11 +435,15 @@
         }
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return CheckedTextView.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(CheckedTextView.class.getName());
         event.setChecked(mChecked);
     }
 
@@ -447,7 +451,6 @@
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(CheckedTextView.class.getName());
         info.setCheckable(true);
         info.setChecked(mChecked);
     }
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 05fc6a1..019d475 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -281,17 +281,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(Chronometer.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(Chronometer.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return Chronometer.class.getName();
     }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 41a3915..fede493 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -324,11 +324,15 @@
         }
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return CompoundButton.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(CompoundButton.class.getName());
         event.setChecked(mChecked);
     }
 
@@ -336,7 +340,6 @@
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(CompoundButton.class.getName());
         info.setCheckable(true);
         info.setChecked(mChecked);
     }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0f0cd2e..7c6055a 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -296,18 +296,9 @@
         mDelegate.onPopulateAccessibilityEvent(event);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        mDelegate.onInitializeAccessibilityEvent(event);
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        mDelegate.onInitializeAccessibilityNodeInfo(info);
+    public CharSequence getAccessibilityClassName() {
+        return DatePicker.class.getName();
     }
 
     @Override
@@ -476,8 +467,6 @@
 
         boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
         void onPopulateAccessibilityEvent(AccessibilityEvent event);
-        void onInitializeAccessibilityEvent(AccessibilityEvent event);
-        void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
     }
 
     /**
@@ -892,16 +881,6 @@
             event.getText().add(selectedDateUtterance);
         }
 
-        @Override
-        public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-            event.setClassName(DatePicker.class.getName());
-        }
-
-        @Override
-        public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-            info.setClassName(DatePicker.class.getName());
-        }
-
         /**
          * Sets the current locale.
          *
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index a3b834e5..85b4d30 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -584,14 +584,8 @@
         event.getText().add(mCurrentDate.getTime().toString());
     }
 
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        event.setClassName(DatePicker.class.getName());
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        info.setClassName(DatePicker.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return DatePicker.class.getName();
     }
 
     @Override
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index 372bdb3..b936a5b 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -115,19 +115,9 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
+    public CharSequence getAccessibilityClassName() {
         //noinspection deprecation
-        event.setClassName(DigitalClock.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        //noinspection deprecation
-        info.setClassName(DigitalClock.class.getName());
+        return DigitalClock.class.getName();
     }
 }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index f54beb5..24cc2d8 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -122,18 +122,9 @@
         super.setEllipsize(ellipsis);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(EditText.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(EditText.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return EditText.class.getName();
     }
 
     /** @hide */
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 675dc9bb..323ddb6 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -1341,17 +1341,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ExpandableListView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ExpandableListView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ExpandableListView.class.getName();
     }
 }
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index f208fff..57bbc42 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -203,11 +204,15 @@
     }
 
     @Override
-    @RemotableViewMethod
-    public void setVisibility(@Visibility int visibility) {
-        super.setVisibility(visibility);
-        if (mForeground != null) {
-            mForeground.setVisible(visibility == VISIBLE, false);
+    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+
+        final Drawable dr = mForeground;
+        if (dr != null) {
+            final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
+            if (visible != dr.isVisible()) {
+                dr.setVisible(visible, false);
+            }
         }
     }
 
@@ -703,19 +708,9 @@
         return new LayoutParams(p);
     }
 
-
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(FrameLayout.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(FrameLayout.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return FrameLayout.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 3c428b0..ac19e6d 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -1373,18 +1373,15 @@
 
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(Gallery.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return Gallery.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(Gallery.class.getName());
         info.setScrollable(mItemCount > 1);
         if (isEnabled()) {
             if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index cc925ebc..41ddc98 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -1190,18 +1190,9 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(GridLayout.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(GridLayout.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return GridLayout.class.getName();
     }
 
     // Inner classes
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index f7ce57b..8b2217c 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -2341,18 +2341,15 @@
         return result;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(GridView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return GridView.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(GridView.class.getName());
 
         final int columnsCount = getNumColumns();
         final int rowsCount = getCount() / columnsCount;
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index f1fa1b6..b37495f 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -795,11 +795,15 @@
         return false;
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return HorizontalScrollView.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(HorizontalScrollView.class.getName());
         final int scrollRange = getScrollRange();
         if (scrollRange > 0) {
             info.setScrollable(true);
@@ -816,7 +820,6 @@
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(HorizontalScrollView.class.getName());
         event.setScrollable(getScrollRange() > 0);
         event.setScrollX(mScrollX);
         event.setScrollY(mScrollY);
diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java
index 3b6825d..22f9c10 100644
--- a/core/java/android/widget/ImageButton.java
+++ b/core/java/android/widget/ImageButton.java
@@ -92,17 +92,8 @@
         return false;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ImageButton.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ImageButton.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ImageButton.class.getName();
     }
 }
diff --git a/core/java/android/widget/ImageSwitcher.java b/core/java/android/widget/ImageSwitcher.java
index 0910eb0..80e908a 100644
--- a/core/java/android/widget/ImageSwitcher.java
+++ b/core/java/android/widget/ImageSwitcher.java
@@ -56,17 +56,8 @@
         showNext();
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ImageSwitcher.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ImageSwitcher.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ImageSwitcher.class.getName();
     }
 }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index fbad314..757038c 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -1419,17 +1419,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ImageView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ImageView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ImageView.class.getName();
     }
 }
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 28e50c4..c0f63d2 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1806,18 +1806,9 @@
         return p instanceof LinearLayout.LayoutParams;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(LinearLayout.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(LinearLayout.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return LinearLayout.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index df0d1fd..0aaef6d 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3878,18 +3878,15 @@
         return false;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ListView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ListView.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ListView.class.getName());
 
         final int rowsCount = getCount();
         final int selectionMode = getSelectionModeForAccessibility();
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 4cafe72..380b328 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -625,18 +625,9 @@
         super.setEnabled(enabled);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(MediaController.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(MediaController.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return MediaController.class.getName();
     }
 
     private View.OnClickListener mRewListener = new View.OnClickListener() {
diff --git a/core/java/android/widget/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java
index 6954eea..c10e581 100644
--- a/core/java/android/widget/MultiAutoCompleteTextView.java
+++ b/core/java/android/widget/MultiAutoCompleteTextView.java
@@ -202,18 +202,9 @@
         editable.replace(start, end, mTokenizer.terminateToken(text));
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(MultiAutoCompleteTextView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(MultiAutoCompleteTextView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return MultiAutoCompleteTextView.class.getName();
     }
 
     public static interface Tokenizer {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index f5cd915..a929f3d 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -27,6 +27,11 @@
 import android.graphics.drawable.StateListDrawable;
 import android.os.Build;
 import android.os.IBinder;
+import android.transition.Transition;
+import android.transition.Transition.EpicenterCallback;
+import android.transition.TransitionInflater;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.KeyEvent;
@@ -39,12 +44,13 @@
 import android.view.WindowManager;
 
 import java.lang.ref.WeakReference;
+import java.util.List;
 
 /**
  * <p>A popup window that can be used to display an arbitrary view. The popup
  * window is a floating container that appears on top of the current
  * activity.</p>
- * 
+ *
  * @see android.widget.AutoCompleteTextView
  * @see android.widget.Spinner
  */
@@ -56,7 +62,7 @@
      * it doesn't.
      */
     public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
-    
+
     /**
      * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
      * work with an input method, regardless of whether it is focusable.  This
@@ -64,7 +70,7 @@
      * the input method while it is shown.
      */
     public static final int INPUT_METHOD_NEEDED = 1;
-    
+
     /**
      * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
      * work with an input method, regardless of whether it is focusable.  This
@@ -75,14 +81,32 @@
 
     private static final int DEFAULT_ANCHORED_GRAVITY = Gravity.TOP | Gravity.START;
 
+    /**
+     * Default animation style indicating that separate animations should be
+     * used for top/bottom anchoring states.
+     */
+    private static final int ANIMATION_STYLE_DEFAULT = -1;
+
+    private final int[] mDrawingLocation = new int[2];
+    private final int[] mScreenLocation = new int[2];
+    private final Rect mTempRect = new Rect();
+    private final Rect mAnchorBounds = new Rect();
+
     private Context mContext;
     private WindowManager mWindowManager;
-    
+
     private boolean mIsShowing;
     private boolean mIsDropdown;
 
+    /** View that handles event dispatch and content transitions. */
+    private PopupDecorView mDecorView;
+
+    /** View that holds the popup background. May be the content view. */
+    private View mBackgroundView;
+
+    /** The contents of the popup. */
     private View mContentView;
-    private View mPopupView;
+
     private boolean mFocusable;
     private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE;
     private int mSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
@@ -112,49 +136,67 @@
 
     private float mElevation;
 
-    private int[] mDrawingLocation = new int[2];
-    private int[] mScreenLocation = new int[2];
-    private Rect mTempRect = new Rect();
-    
     private Drawable mBackground;
     private Drawable mAboveAnchorBackgroundDrawable;
     private Drawable mBelowAnchorBackgroundDrawable;
 
-    // Temporary animation centers. Should be moved into window params?
-    private int mAnchorRelativeX;
-    private int mAnchorRelativeY;
+    private Transition mEnterTransition;
+    private Transition mExitTransition;
 
     private boolean mAboveAnchor;
     private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
-    
+
     private OnDismissListener mOnDismissListener;
     private boolean mIgnoreCheekPress = false;
 
-    private int mAnimationStyle = -1;
-    
+    private int mAnimationStyle = ANIMATION_STYLE_DEFAULT;
+
     private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
         com.android.internal.R.attr.state_above_anchor
     };
 
     private WeakReference<View> mAnchor;
 
-    private final OnScrollChangedListener mOnScrollChangedListener =
-        new OnScrollChangedListener() {
-            @Override
-            public void onScrollChanged() {
-                final View anchor = mAnchor != null ? mAnchor.get() : null;
-                if (anchor != null && mPopupView != null) {
-                    final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
-                            mPopupView.getLayoutParams();
-
-                    updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
-                            mAnchoredGravity));
-                    update(p.x, p.y, -1, -1, true);
-                }
+    private final EpicenterCallback mEpicenterCallback = new EpicenterCallback() {
+        @Override
+        public Rect onGetEpicenter(Transition transition) {
+            final View anchor = mAnchor.get();
+            final View decor = mDecorView;
+            if (anchor == null || decor == null) {
+                return null;
             }
-        };
 
-    private int mAnchorXoff, mAnchorYoff, mAnchoredGravity;
+            final Rect anchorBounds = mAnchorBounds;
+            final int[] anchorLocation = mAnchor.get().getLocationOnScreen();
+            final int[] popupLocation = mDecorView.getLocationOnScreen();
+
+            // Compute the position of the anchor relative to the popup.
+            anchorBounds.set(0, 0, anchor.getWidth(), anchor.getHeight());
+            anchorBounds.offset(anchorLocation[0] - popupLocation[0],
+                    anchorLocation[1] - popupLocation[1]);
+
+            return anchorBounds;
+        }
+    };
+
+    private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() {
+        @Override
+        public void onScrollChanged() {
+            final View anchor = mAnchor != null ? mAnchor.get() : null;
+            if (anchor != null && mDecorView != null) {
+                final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
+                        mDecorView.getLayoutParams();
+
+                updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
+                        mAnchoredGravity));
+                update(p.x, p.y, -1, -1, true);
+            }
+        }
+    };
+
+    private int mAnchorXoff;
+    private int mAnchorYoff;
+    private int mAnchoredGravity;
     private boolean mOverlapAnchor;
 
     private boolean mPopupViewInitialLayoutDirectionInherited;
@@ -185,10 +227,10 @@
     public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
-    
+
     /**
      * <p>Create a new, empty, non focusable popup window of dimension (0,0).</p>
-     * 
+     *
      * <p>The popup does not provide a background.</p>
      */
     public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
@@ -201,11 +243,34 @@
         mElevation = a.getDimension(R.styleable.PopupWindow_popupElevation, 0);
         mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
 
-        final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, -1);
-        mAnimationStyle = animStyle == R.style.Animation_PopupWindow ? -1 : animStyle;
+        // Preserve default behavior from Gingerbread. If the animation is
+        // undefined or explicitly specifies the Gingerbread animation style,
+        // use a sentinel value.
+        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupAnimationStyle)) {
+            final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, 0);
+            if (animStyle == R.style.Animation_PopupWindow) {
+                mAnimationStyle = ANIMATION_STYLE_DEFAULT;
+            } else {
+                mAnimationStyle = animStyle;
+            }
+        } else {
+            mAnimationStyle = ANIMATION_STYLE_DEFAULT;
+        }
+
+        final Transition enterTransition = getTransition(a.getResourceId(
+                R.styleable.PopupWindow_popupEnterTransition, 0));
+        final Transition exitTransition;
+        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupExitTransition)) {
+            exitTransition = getTransition(a.getResourceId(
+                    R.styleable.PopupWindow_popupExitTransition, 0));
+        } else {
+            exitTransition = enterTransition == null ? null : enterTransition.clone();
+        }
 
         a.recycle();
 
+        setEnterTransition(enterTransition);
+        setExitTransition(exitTransition);
         setBackgroundDrawable(bg);
     }
 
@@ -286,6 +351,37 @@
         setFocusable(focusable);
     }
 
+    public void setEnterTransition(Transition enterTransition) {
+        mEnterTransition = enterTransition;
+
+        if (mEnterTransition != null) {
+            mEnterTransition.setEpicenterCallback(mEpicenterCallback);
+        }
+    }
+
+    public void setExitTransition(Transition exitTransition) {
+        mExitTransition = exitTransition;
+
+        if (mExitTransition != null) {
+            mExitTransition.setEpicenterCallback(mEpicenterCallback);
+        }
+    }
+
+    private Transition getTransition(int resId) {
+        if (resId != 0 && resId != R.transition.no_transition) {
+            final TransitionInflater inflater = TransitionInflater.from(mContext);
+            final Transition transition = inflater.inflateTransition(resId);
+            if (transition != null) {
+                final boolean isEmpty = transition instanceof TransitionSet
+                        && ((TransitionSet) transition).getTransitionCount() == 0;
+                if (!isEmpty) {
+                    return transition;
+                }
+            }
+        }
+        return null;
+    }
+
     /**
      * Return the drawable used as the popup window's background.
      *
@@ -379,7 +475,7 @@
      * Set the flag on popup to ignore cheek press events; by default this flag
      * is set to false
      * which means the popup will not ignore cheek press dispatch events.
-     * 
+     *
      * <p>If the popup is showing, calling this method will take effect only
      * the next time the popup is shown or through a manual call to one of
      * the {@link #update()} methods.</p>
@@ -389,7 +485,7 @@
     public void setIgnoreCheekPress() {
         mIgnoreCheekPress = true;
     }
-    
+
 
     /**
      * <p>Change the animation style resource for this popup.</p>
@@ -401,13 +497,13 @@
      * @param animationStyle animation style to use when the popup appears
      *      and disappears.  Set to -1 for the default animation, 0 for no
      *      animation, or a resource identifier for an explicit animation.
-     *      
+     *
      * @see #update()
      */
     public void setAnimationStyle(int animationStyle) {
         mAnimationStyle = animationStyle;
     }
-    
+
     /**
      * <p>Return the view used as the content of the popup window.</p>
      *
@@ -491,7 +587,7 @@
      * @param focusable true if the popup should grab focus, false otherwise.
      *
      * @see #isFocusable()
-     * @see #isShowing() 
+     * @see #isShowing()
      * @see #update()
      */
     public void setFocusable(boolean focusable) {
@@ -500,23 +596,23 @@
 
     /**
      * Return the current value in {@link #setInputMethodMode(int)}.
-     * 
+     *
      * @see #setInputMethodMode(int)
      */
     public int getInputMethodMode() {
         return mInputMethodMode;
-        
+
     }
-    
+
     /**
      * Control how the popup operates with an input method: one of
      * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
      * or {@link #INPUT_METHOD_NOT_NEEDED}.
-     * 
+     *
      * <p>If the popup is showing, calling this method will take effect only
      * the next time the popup is shown or through a manual call to one of
      * the {@link #update()} methods.</p>
-     * 
+     *
      * @see #getInputMethodMode()
      * @see #update()
      */
@@ -547,12 +643,12 @@
     public int getSoftInputMode() {
         return mSoftInputMode;
     }
-    
+
     /**
      * <p>Indicates whether the popup window receives touch events.</p>
-     * 
+     *
      * @return true if the popup is touchable, false otherwise
-     * 
+     *
      * @see #setTouchable(boolean)
      */
     public boolean isTouchable() {
@@ -571,7 +667,7 @@
      * @param touchable true if the popup should receive touch events, false otherwise
      *
      * @see #isTouchable()
-     * @see #isShowing() 
+     * @see #isShowing()
      * @see #update()
      */
     public void setTouchable(boolean touchable) {
@@ -581,9 +677,9 @@
     /**
      * <p>Indicates whether the popup window will be informed of touch events
      * outside of its window.</p>
-     * 
+     *
      * @return true if the popup is outside touchable, false otherwise
-     * 
+     *
      * @see #setOutsideTouchable(boolean)
      */
     public boolean isOutsideTouchable() {
@@ -604,7 +700,7 @@
      * touch events, false otherwise
      *
      * @see #isOutsideTouchable()
-     * @see #isShowing() 
+     * @see #isShowing()
      * @see #update()
      */
     public void setOutsideTouchable(boolean touchable) {
@@ -613,9 +709,9 @@
 
     /**
      * <p>Indicates whether clipping of the popup window is enabled.</p>
-     * 
+     *
      * @return true if the clipping is enabled, false otherwise
-     * 
+     *
      * @see #setClippingEnabled(boolean)
      */
     public boolean isClippingEnabled() {
@@ -626,13 +722,13 @@
      * <p>Allows the popup window to extend beyond the bounds of the screen. By default the
      * window is clipped to the screen boundaries. Setting this to false will allow windows to be
      * accurately positioned.</p>
-     * 
+     *
      * <p>If the popup is showing, calling this method will take effect only
      * the next time the popup is shown or through a manual call to one of
      * the {@link #update()} methods.</p>
      *
      * @param enabled false if the window should be allowed to extend outside of the screen
-     * @see #isShowing() 
+     * @see #isShowing()
      * @see #isClippingEnabled()
      * @see #update()
      */
@@ -660,12 +756,12 @@
     void setAllowScrollingAnchorParent(boolean enabled) {
         mAllowScrollingAnchorParent = enabled;
     }
-    
+
     /**
      * <p>Indicates whether the popup window supports splitting touches.</p>
-     * 
+     *
      * @return true if the touch splitting is enabled, false otherwise
-     * 
+     *
      * @see #setSplitTouchEnabled(boolean)
      */
     public boolean isSplitTouchEnabled() {
@@ -794,7 +890,7 @@
      * window manager by the popup.  By default these are 0, meaning that
      * the current width or height is requested as an explicit size from
      * the window manager.  You can supply
-     * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or 
+     * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or
      * {@link ViewGroup.LayoutParams#MATCH_PARENT} to have that measure
      * spec supplied instead, replacing the absolute width and height that
      * has been set in the popup.</p>
@@ -815,7 +911,7 @@
         mWidthMode = widthSpec;
         mHeightMode = heightSpec;
     }
-    
+
     /**
      * <p>Return this popup's height MeasureSpec</p>
      *
@@ -836,7 +932,7 @@
      * @param height the height MeasureSpec of the popup
      *
      * @see #getHeight()
-     * @see #isShowing() 
+     * @see #isShowing()
      */
     public void setHeight(int height) {
         mHeight = height;
@@ -847,7 +943,7 @@
      *
      * @return the width MeasureSpec of the popup
      *
-     * @see #setWidth(int) 
+     * @see #setWidth(int)
      */
     public int getWidth() {
         return mWidth;
@@ -913,7 +1009,7 @@
      * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying
      * <code>Gravity.LEFT | Gravity.TOP</code>.
      * </p>
-     * 
+     *
      * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
      * @param gravity the gravity which controls the placement of the popup window
      * @param x the popup's x location offset
@@ -939,23 +1035,24 @@
             return;
         }
 
+        TransitionManager.endTransitions(mDecorView);
+
         unregisterForScrollChanged();
 
         mIsShowing = true;
         mIsDropdown = false;
 
-        WindowManager.LayoutParams p = createPopupLayout(token);
-        p.windowAnimations = computeAnimationResource();
-       
+        final WindowManager.LayoutParams p = createPopupLayoutParams(token);
         preparePopup(p);
-        if (gravity == Gravity.NO_GRAVITY) {
-            gravity = Gravity.TOP | Gravity.START;
+
+        // Only override the default if some gravity was specified.
+        if (gravity != Gravity.NO_GRAVITY) {
+            p.gravity = gravity;
         }
-        p.gravity = gravity;
+
         p.x = x;
         p.y = y;
-        if (mHeightMode < 0) p.height = mLastHeight = mHeightMode;
-        if (mWidthMode < 0) p.width = mLastWidth = mWidthMode;
+
         invokePopup(p);
     }
 
@@ -1021,20 +1118,18 @@
             return;
         }
 
+        TransitionManager.endTransitions(mDecorView);
+
         registerForScrollChanged(anchor, xoff, yoff, gravity);
 
         mIsShowing = true;
         mIsDropdown = true;
 
-        WindowManager.LayoutParams p = createPopupLayout(anchor.getWindowToken());
+        final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
         preparePopup(p);
 
-        updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, gravity));
-
-        if (mHeightMode < 0) p.height = mLastHeight = mHeightMode;
-        if (mWidthMode < 0) p.width = mLastWidth = mWidthMode;
-
-        p.windowAnimations = computeAnimationResource();
+        final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff, gravity);
+        updateAboveAnchor(aboveAnchor);
 
         invokePopup(p);
     }
@@ -1049,12 +1144,12 @@
                 // do the job.
                 if (mAboveAnchorBackgroundDrawable != null) {
                     if (mAboveAnchor) {
-                        mPopupView.setBackground(mAboveAnchorBackgroundDrawable);
+                        mDecorView.setBackground(mAboveAnchorBackgroundDrawable);
                     } else {
-                        mPopupView.setBackground(mBelowAnchorBackgroundDrawable);
+                        mDecorView.setBackground(mBelowAnchorBackgroundDrawable);
                     }
                 } else {
-                    mPopupView.refreshDrawableState();
+                    mDecorView.refreshDrawableState();
                 }
             }
         }
@@ -1076,10 +1171,9 @@
     }
 
     /**
-     * <p>Prepare the popup by embedding in into a new ViewGroup if the
-     * background drawable is not null. If embedding is required, the layout
-     * parameters' height is modified to take into account the background's
-     * padding.</p>
+     * Prepare the popup by embedding it into a new ViewGroup if the background
+     * drawable is not null. If embedding is required, the layout parameters'
+     * height is modified to take into account the background's padding.
      *
      * @param p the layout parameters of the popup's content view
      */
@@ -1089,36 +1183,79 @@
                     + "calling setContentView() before attempting to show the popup.");
         }
 
+        // When a background is available, we embed the content view within
+        // another view that owns the background drawable.
         if (mBackground != null) {
-            final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
-            int height = ViewGroup.LayoutParams.MATCH_PARENT;
-            if (layoutParams != null &&
-                    layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
-                height = ViewGroup.LayoutParams.WRAP_CONTENT;
-            }
-
-            // when a background is available, we embed the content view
-            // within another view that owns the background drawable
-            PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
-            PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT, height
-            );
-            popupViewContainer.setBackground(mBackground);
-            popupViewContainer.addView(mContentView, listParams);
-
-            mPopupView = popupViewContainer;
+            mBackgroundView = createBackgroundView(mContentView);
+            mBackgroundView.setBackground(mBackground);
         } else {
-            mPopupView = mContentView;
+            mBackgroundView = mContentView;
         }
 
-        mPopupView.setElevation(mElevation);
+        mDecorView = createDecorView(mBackgroundView);
+
+        // The background owner should be elevated so that it casts a shadow.
+        mBackgroundView.setElevation(mElevation);
+
+        // We may wrap that in another view, so we'll need to manually specify
+        // the surface insets.
+        final int surfaceInset = (int) Math.ceil(mBackgroundView.getZ() * 2);
+        p.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+        p.hasManualSurfaceInsets = true;
+
         mPopupViewInitialLayoutDirectionInherited =
-                (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
+                (mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
         mPopupWidth = p.width;
         mPopupHeight = p.height;
     }
 
     /**
+     * Wraps a content view in a PopupViewContainer.
+     *
+     * @param contentView the content view to wrap
+     * @return a PopupViewContainer that wraps the content view
+     */
+    private PopupBackgroundView createBackgroundView(View contentView) {
+        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
+        final int height;
+        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
+            height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        } else {
+            height = ViewGroup.LayoutParams.MATCH_PARENT;
+        }
+
+        final PopupBackgroundView backgroundView = new PopupBackgroundView(mContext);
+        final PopupBackgroundView.LayoutParams listParams = new PopupBackgroundView.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, height);
+        backgroundView.addView(contentView, listParams);
+
+        return backgroundView;
+    }
+
+    /**
+     * Wraps a content view in a FrameLayout.
+     *
+     * @param contentView the content view to wrap
+     * @return a FrameLayout that wraps the content view
+     */
+    private PopupDecorView createDecorView(View contentView) {
+        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
+        final int height;
+        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
+            height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        } else {
+            height = ViewGroup.LayoutParams.MATCH_PARENT;
+        }
+
+        final PopupDecorView decorView = new PopupDecorView(mContext);
+        decorView.addView(contentView, ViewGroup.LayoutParams.MATCH_PARENT, height);
+        decorView.setClipChildren(false);
+        decorView.setClipToPadding(false);
+
+        return decorView;
+    }
+
+    /**
      * <p>Invoke the popup window by adding the content view to the window
      * manager.</p>
      *
@@ -1130,16 +1267,34 @@
         if (mContext != null) {
             p.packageName = mContext.getPackageName();
         }
-        mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
+
+        final View rootView = mContentView.getRootView();
+        rootView.setFitsSystemWindows(mLayoutInsetDecor);
         setLayoutDirectionFromAnchor();
-        mWindowManager.addView(mPopupView, p);
+
+        mWindowManager.addView(rootView, p);
+
+        // Postpone enter transition until the scene root has been laid out.
+        if (mEnterTransition != null) {
+            mEnterTransition.addTarget(mBackgroundView);
+            mEnterTransition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    transition.removeListener(this);
+                    transition.removeTarget(mBackgroundView);
+                }
+            });
+
+            mDecorView.getViewTreeObserver().addOnGlobalLayoutListener(
+                    new PostLayoutTransitionListener(mDecorView, mEnterTransition));
+        }
     }
 
     private void setLayoutDirectionFromAnchor() {
         if (mAnchor != null) {
             View anchor = mAnchor.get();
             if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
-                mPopupView.setLayoutDirection(anchor.getLayoutDirection());
+                mDecorView.setLayoutDirection(anchor.getLayoutDirection());
             }
         }
     }
@@ -1151,26 +1306,39 @@
      *
      * @return the layout parameters to pass to the window manager
      */
-    private WindowManager.LayoutParams createPopupLayout(IBinder token) {
-        // generates the layout parameters for the drop down
-        // we want a fixed size view located at the bottom left of the anchor
-        WindowManager.LayoutParams p = new WindowManager.LayoutParams();
-        // these gravity settings put the view at the top left corner of the
-        // screen. The view is then positioned to the appropriate location
-        // by setting the x and y offsets to match the anchor's bottom
-        // left corner
+    private WindowManager.LayoutParams createPopupLayoutParams(IBinder token) {
+        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
+
+        // These gravity settings put the view at the top left corner of the
+        // screen. The view is then positioned to the appropriate location by
+        // setting the x and y offsets to match the anchor's bottom-left
+        // corner.
         p.gravity = Gravity.START | Gravity.TOP;
-        p.width = mLastWidth = mWidth;
-        p.height = mLastHeight = mHeight;
+        p.flags = computeFlags(p.flags);
+        p.type = mWindowLayoutType;
+        p.token = token;
+        p.softInputMode = mSoftInputMode;
+        p.windowAnimations = computeAnimationResource();
+
         if (mBackground != null) {
             p.format = mBackground.getOpacity();
         } else {
             p.format = PixelFormat.TRANSLUCENT;
         }
-        p.flags = computeFlags(p.flags);
-        p.type = mWindowLayoutType;
-        p.token = token;
-        p.softInputMode = mSoftInputMode;
+
+        if (mHeightMode < 0) {
+            p.height = mLastHeight = mHeightMode;
+        } else {
+            p.height = mLastHeight = mHeight;
+        }
+
+        if (mWidthMode < 0) {
+            p.width = mLastWidth = mWidthMode;
+        } else {
+            p.width = mLastWidth = mWidth;
+        }
+
+        // Used for debugging.
         p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
 
         return p;
@@ -1224,7 +1392,7 @@
     }
 
     private int computeAnimationResource() {
-        if (mAnimationStyle == -1) {
+        if (mAnimationStyle == ANIMATION_STYLE_DEFAULT) {
             if (mIsDropdown) {
                 return mAboveAnchor
                         ? com.android.internal.R.style.Animation_DropDownUp
@@ -1243,7 +1411,7 @@
      * <p>
      * The height must have been set on the layout parameters prior to calling
      * this method.
-     * 
+     *
      * @param anchor the view on which the popup window must be anchored
      * @param p the layout parameters used to display the drop down
      * @param xoff horizontal offset used to adjust for background padding
@@ -1341,19 +1509,15 @@
 
         p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
 
-        // Compute the position of the anchor relative to the popup.
-        mAnchorRelativeX = mDrawingLocation[0] - p.x + anchorHeight / 2;
-        mAnchorRelativeY = mDrawingLocation[1] - p.y + anchorWidth / 2;
-
         return onTop;
     }
-    
+
     /**
      * Returns the maximum height that is available for the popup to be
      * completely shown. It is recommended that this height be the maximum for
      * the popup's height, otherwise it is possible that the popup will be
      * clipped.
-     * 
+     *
      * @param anchor The view on which the popup window must be anchored.
      * @return The maximum available height for the popup to be completely
      *         shown.
@@ -1376,14 +1540,14 @@
     public int getMaxAvailableHeight(View anchor, int yOffset) {
         return getMaxAvailableHeight(anchor, yOffset, false);
     }
-    
+
     /**
      * Returns the maximum height that is available for the popup to be
      * completely shown, optionally ignoring any bottom decorations such as
      * the input method. It is recommended that this height be the maximum for
      * the popup's height, otherwise it is possible that the popup will be
      * clipped.
-     * 
+     *
      * @param anchor The view on which the popup window must be anchored.
      * @param yOffset y offset from the view's bottom edge
      * @param ignoreBottomDecorations if true, the height returned will be
@@ -1391,7 +1555,7 @@
      *        bottom decorations
      * @return The maximum available height for the popup to be completely
      *         shown.
-     *         
+     *
      * @hide Pending API council approval.
      */
     public int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) {
@@ -1400,7 +1564,7 @@
 
         final int[] anchorPos = mDrawingLocation;
         anchor.getLocationOnScreen(anchorPos);
-        
+
         int bottomEdge = displayFrame.bottom;
         if (ignoreBottomDecorations) {
             Resources res = anchor.getContext().getResources();
@@ -1413,49 +1577,83 @@
         int returnedHeight = Math.max(distanceToBottom, distanceToTop);
         if (mBackground != null) {
             mBackground.getPadding(mTempRect);
-            returnedHeight -= mTempRect.top + mTempRect.bottom; 
+            returnedHeight -= mTempRect.top + mTempRect.bottom;
         }
-        
+
         return returnedHeight;
     }
-    
+
     /**
-     * <p>Dispose of the popup window. This method can be invoked only after
-     * {@link #showAsDropDown(android.view.View)} has been executed. Failing that, calling
-     * this method will have no effect.</p>
+     * Disposes of the popup window. This method can be invoked only after
+     * {@link #showAsDropDown(android.view.View)} has been executed. Failing
+     * that, calling this method will have no effect.
      *
-     * @see #showAsDropDown(android.view.View) 
+     * @see #showAsDropDown(android.view.View)
      */
     public void dismiss() {
-        if (isShowing() && mPopupView != null) {
-            mIsShowing = false;
+        if (!isShowing()) {
+            return;
+        }
 
-            unregisterForScrollChanged();
+        unregisterForScrollChanged();
 
-            try {
-                mWindowManager.removeViewImmediate(mPopupView);
-            } finally {
-                if (mPopupView != mContentView && mPopupView instanceof ViewGroup) {
-                    ((ViewGroup) mPopupView).removeView(mContentView);
+        mIsShowing = false;
+
+        if (mExitTransition != null) {
+            // Cache the content view, since it may change without notice.
+            final View contentView = mContentView;
+
+            mExitTransition.addTarget(mBackgroundView);
+            mExitTransition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    transition.removeListener(this);
+                    transition.removeTarget(mBackgroundView);
+
+                    dismissImmediate(contentView);
                 }
-                mPopupView = null;
+            });
 
-                if (mOnDismissListener != null) {
-                    mOnDismissListener.onDismiss();
-                }
+            TransitionManager.beginDelayedTransition(mDecorView, mExitTransition);
+
+            // Transition to invisible.
+            mBackgroundView.setVisibility(View.INVISIBLE);
+        } else {
+            dismissImmediate(mContentView);
+        }
+
+        if (mOnDismissListener != null) {
+            mOnDismissListener.onDismiss();
+        }
+    }
+
+    /**
+     * Removes the popup from the window manager and tears down the supporting
+     * view hierarchy, if necessary.
+     */
+    private void dismissImmediate(View contentView) {
+        try {
+            mWindowManager.removeViewImmediate(mDecorView);
+        } finally {
+            mDecorView.removeView(mBackgroundView);
+            mDecorView = null;
+
+            if (mBackgroundView != contentView) {
+                ((ViewGroup) mBackgroundView).removeView(contentView);
             }
+            mBackgroundView = null;
         }
     }
 
     /**
      * Sets the listener to be called when the window is dismissed.
-     * 
+     *
      * @param onDismissListener The listener.
      */
     public void setOnDismissListener(OnDismissListener onDismissListener) {
         mOnDismissListener = onDismissListener;
     }
-    
+
     /**
      * Updates the state of the popup window, if it is currently being displayed,
      * from the currently set state.  This includes:
@@ -1467,12 +1665,12 @@
         if (!isShowing() || mContentView == null) {
             return;
         }
-        
-        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
-                mPopupView.getLayoutParams();
-        
+
+        final WindowManager.LayoutParams p =
+                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
+
         boolean update = false;
-        
+
         final int newAnim = computeAnimationResource();
         if (newAnim != p.windowAnimations) {
             p.windowAnimations = newAnim;
@@ -1487,7 +1685,7 @@
 
         if (update) {
             setLayoutDirectionFromAnchor();
-            mWindowManager.updateViewLayout(mPopupView, p);
+            mWindowManager.updateViewLayout(mDecorView, p);
         }
     }
 
@@ -1500,11 +1698,11 @@
      * @param height the new height
      */
     public void update(int width, int height) {
-        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
-                mPopupView.getLayoutParams();
+        final WindowManager.LayoutParams p =
+                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
         update(p.x, p.y, width, height, false);
     }
-    
+
     /**
      * <p>Updates the position and the dimension of the popup window. Width and
      * height can be set to -1 to update location only.  Calling this function
@@ -1548,7 +1746,8 @@
             return;
         }
 
-        WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
+        final WindowManager.LayoutParams p =
+                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
 
         boolean update = force;
 
@@ -1588,7 +1787,7 @@
 
         if (update) {
             setLayoutDirectionFromAnchor();
-            mWindowManager.updateViewLayout(mPopupView, p);
+            mWindowManager.updateViewLayout(mDecorView, p);
         }
     }
 
@@ -1655,7 +1854,7 @@
         }
 
         final WindowManager.LayoutParams p =
-                (WindowManager.LayoutParams) mPopupView.getLayoutParams();
+                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
         final int x = p.x;
         final int y = p.y;
         if (updateLocation) {
@@ -1679,23 +1878,22 @@
     }
 
     private void unregisterForScrollChanged() {
-        WeakReference<View> anchorRef = mAnchor;
-        View anchor = null;
-        if (anchorRef != null) {
-            anchor = anchorRef.get();
-        }
+        final WeakReference<View> anchorRef = mAnchor;
+        final View anchor = anchorRef == null ? null : anchorRef.get();
         if (anchor != null) {
-            ViewTreeObserver vto = anchor.getViewTreeObserver();
+            final ViewTreeObserver vto = anchor.getViewTreeObserver();
             vto.removeOnScrollChangedListener(mOnScrollChangedListener);
         }
+
         mAnchor = null;
     }
 
     private void registerForScrollChanged(View anchor, int xoff, int yoff, int gravity) {
         unregisterForScrollChanged();
 
-        mAnchor = new WeakReference<View>(anchor);
-        ViewTreeObserver vto = anchor.getViewTreeObserver();
+        mAnchor = new WeakReference<>(anchor);
+
+        final ViewTreeObserver vto = anchor.getViewTreeObserver();
         if (vto != null) {
             vto.addOnScrollChangedListener(mOnScrollChangedListener);
         }
@@ -1705,23 +1903,49 @@
         mAnchoredGravity = gravity;
     }
 
-    private class PopupViewContainer extends FrameLayout {
-        private static final String TAG = "PopupWindow.PopupViewContainer";
+    /**
+     * Layout listener used to run a transition immediately after a view is
+     * laid out. Forces the view to transition from invisible to visible.
+     */
+    private static class PostLayoutTransitionListener implements
+            ViewTreeObserver.OnGlobalLayoutListener {
+        private final ViewGroup mSceneRoot;
+        private final Transition mTransition;
 
-        public PopupViewContainer(Context context) {
-            super(context);
+        public PostLayoutTransitionListener(ViewGroup sceneRoot, Transition transition) {
+            mSceneRoot = sceneRoot;
+            mTransition = transition;
         }
 
         @Override
-        protected int[] onCreateDrawableState(int extraSpace) {
-            if (mAboveAnchor) {
-                // 1 more needed for the above anchor state
-                final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
-                View.mergeDrawableStates(drawableState, ABOVE_ANCHOR_STATE_SET);
-                return drawableState;
-            } else {
-                return super.onCreateDrawableState(extraSpace);
+        public void onGlobalLayout() {
+            final ViewTreeObserver observer = mSceneRoot.getViewTreeObserver();
+            if (observer == null) {
+                // View has been detached.
+                return;
             }
+
+            observer.removeOnGlobalLayoutListener(this);
+
+            // Set all targets to be initially invisible.
+            final List<View> targets = mTransition.getTargets();
+            final int N = targets.size();
+            for (int i = 0; i < N; i++) {
+                targets.get(i).setVisibility(View.INVISIBLE);
+            }
+
+            TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
+
+            // Transition targets to visible.
+            for (int i = 0; i < N; i++) {
+                targets.get(i).setVisibility(View.VISIBLE);
+            }
+        }
+    }
+
+    private class PopupDecorView extends FrameLayout {
+        public PopupDecorView(Context context) {
+            super(context);
         }
 
         @Override
@@ -1731,15 +1955,14 @@
                     return super.dispatchKeyEvent(event);
                 }
 
-                if (event.getAction() == KeyEvent.ACTION_DOWN
-                        && event.getRepeatCount() == 0) {
-                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
                     if (state != null) {
                         state.startTracking(event, this);
                     }
                     return true;
                 } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
                     if (state != null && state.isTracking(event) && !event.isCanceled()) {
                         dismiss();
                         return true;
@@ -1763,7 +1986,7 @@
         public boolean onTouchEvent(MotionEvent event) {
             final int x = (int) event.getX();
             final int y = (int) event.getY();
-            
+
             if ((event.getAction() == MotionEvent.ACTION_DOWN)
                     && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
                 dismiss();
@@ -1775,17 +1998,22 @@
                 return super.onTouchEvent(event);
             }
         }
+    }
 
-    /** @hide */
+    private class PopupBackgroundView extends FrameLayout {
+        public PopupBackgroundView(Context context) {
+            super(context);
+        }
+
         @Override
-        public void sendAccessibilityEventInternal(int eventType) {
-            // clinets are interested in the content not the container, make it event source
-            if (mContentView != null) {
-                mContentView.sendAccessibilityEvent(eventType);
+        protected int[] onCreateDrawableState(int extraSpace) {
+            if (mAboveAnchor) {
+                final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+                View.mergeDrawableStates(drawableState, ABOVE_ANCHOR_STATE_SET);
+                return drawableState;
             } else {
-                super.sendAccessibilityEventInternal(eventType);
+                return super.onCreateDrawableState(extraSpace);
             }
         }
     }
-    
 }
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index d32cb10..9c3296b 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1825,20 +1825,17 @@
         mAttached = false;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ProgressBar.class.getName());
-        event.setItemCount(mMax);
-        event.setCurrentItemIndex(mProgress);
+    public CharSequence getAccessibilityClassName() {
+        return ProgressBar.class.getName();
     }
 
     /** @hide */
     @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ProgressBar.class.getName());
+    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEventInternal(event);
+        event.setItemCount(mMax);
+        event.setCurrentItemIndex(mProgress);
     }
 
     /**
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index d0e8081..3068de9 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -304,18 +304,9 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(QuickContactBadge.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(QuickContactBadge.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return QuickContactBadge.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/RadioButton.java b/core/java/android/widget/RadioButton.java
index 82280b4..aebc1b6 100644
--- a/core/java/android/widget/RadioButton.java
+++ b/core/java/android/widget/RadioButton.java
@@ -79,17 +79,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(RadioButton.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(RadioButton.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return RadioButton.class.getName();
     }
 }
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index c0f60eb..f04bb3d 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -240,18 +240,9 @@
         return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(RadioGroup.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(RadioGroup.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return RadioGroup.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
index 2d0649d..4268961 100644
--- a/core/java/android/widget/RatingBar.java
+++ b/core/java/android/widget/RatingBar.java
@@ -330,18 +330,9 @@
         
         super.setMax(max);
     }
-    
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(RatingBar.class.getName());
-    }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(RatingBar.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return RatingBar.class.getName();
     }
 }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 71f4da0..89b1d54 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1103,18 +1103,9 @@
         return false;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(RelativeLayout.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(RelativeLayout.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return RelativeLayout.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index b12c581..6fd90c3 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -44,6 +44,7 @@
     private boolean mRangeChanged;
     private boolean mAlwaysDrawHorizontalTrack;
     private boolean mAlwaysDrawVerticalTrack;
+    private boolean mMutated;
 
     private int mAlpha = 255;
     private boolean mHasSetAlpha;
@@ -266,6 +267,10 @@
 
     private void propagateCurrentState(Drawable d) {
         if (d != null) {
+            if (mMutated) {
+                d.mutate();
+            }
+
             d.setState(getState());
             d.setCallback(this);
 
@@ -290,6 +295,26 @@
     }
 
     @Override
+    public ScrollBarDrawable mutate() {
+        if (!mMutated && super.mutate() == this) {
+            if (mVerticalTrack != null) {
+                mVerticalTrack.mutate();
+            }
+            if (mVerticalThumb != null) {
+                mVerticalThumb.mutate();
+            }
+            if (mHorizontalTrack != null) {
+                mHorizontalTrack.mutate();
+            }
+            if (mHorizontalThumb != null) {
+                mHorizontalThumb.mutate();
+            }
+            mMutated = true;
+        }
+        return this;
+    }
+
+    @Override
     public void setAlpha(int alpha) {
         mAlpha = alpha;
         mHasSetAlpha = true;
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 1098419..b95c27d 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -839,11 +839,15 @@
         return false;
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return ScrollView.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ScrollView.class.getName());
         if (isEnabled()) {
             final int scrollRange = getScrollRange();
             if (scrollRange > 0) {
@@ -862,7 +866,6 @@
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ScrollView.class.getName());
         final boolean scrollable = getScrollRange() > 0;
         event.setScrollable(scrollable);
         event.setScrollX(mScrollX);
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index a1f361a..8846421 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1325,18 +1325,9 @@
         setIconified(false);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(SearchView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(SearchView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return SearchView.class.getName();
     }
 
     private void adjustDropDownSizeAndPosition() {
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index aa5c055..e97bdf25 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -124,17 +124,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(SeekBar.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(SeekBar.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return SeekBar.class.getName();
     }
 }
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index e3f4a10..272f4b0 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -837,18 +837,9 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(SlidingDrawer.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(SlidingDrawer.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return SlidingDrawer.class.getName();
     }
 
     private void closeDrawer() {
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index a6e0e6d..6ee2b4c 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -765,18 +765,15 @@
         dialog.dismiss();
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(Spinner.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return Spinner.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(Spinner.class.getName());
 
         if (mAdapter != null) {
             info.setCanOpenPopup(true);
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 2aa1c09..803ba4b 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1224,18 +1224,15 @@
         measureChildren();
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(StackView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return StackView.class.getName();
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(StackView.class.getName());
         info.setScrollable(getChildCount() > 1);
         if (isEnabled()) {
             if (getDisplayedChild() < getChildCount() - 1) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 13d6b42..b959ddc 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -24,10 +25,12 @@
 import android.graphics.Canvas;
 import android.graphics.Insets;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Typeface;
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.text.Layout;
 import android.text.StaticLayout;
 import android.text.TextPaint;
@@ -41,6 +44,7 @@
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
 import android.view.VelocityTracker;
+import android.view.ViewAssistData;
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -84,7 +88,17 @@
     private static final int MONOSPACE = 3;
 
     private Drawable mThumbDrawable;
+    private ColorStateList mThumbTintList = null;
+    private PorterDuff.Mode mThumbTintMode = null;
+    private boolean mHasThumbTint = false;
+    private boolean mHasThumbTintMode = false;
+
     private Drawable mTrackDrawable;
+    private ColorStateList mTrackTintList = null;
+    private PorterDuff.Mode mTrackTintMode = null;
+    private boolean mHasTrackTint = false;
+    private boolean mHasTrackTintMode = false;
+
     private int mThumbTextPadding;
     private int mSwitchMinWidth;
     private int mSwitchPadding;
@@ -473,6 +487,86 @@
     }
 
     /**
+     * Applies a tint to the track drawable. Does not modify the current
+     * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+     * <p>
+     * Subsequent calls to {@link #setTrackDrawable(Drawable)} will
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#Switch_trackTint
+     * @see #getTrackTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    public void setTrackTintList(@Nullable ColorStateList tint) {
+        mTrackTintList = tint;
+        mHasTrackTint = true;
+
+        applyTrackTint();
+    }
+
+    /**
+     * @return the tint applied to the track drawable
+     * @attr ref android.R.styleable#Switch_trackTint
+     * @see #setTrackTintList(ColorStateList)
+     */
+    @Nullable
+    public ColorStateList getTrackTintList() {
+        return mTrackTintList;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setTrackTintList(ColorStateList)}} to the track drawable.
+     * The default mode is {@link PorterDuff.Mode#SRC_IN}.
+     *
+     * @param tintMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#Switch_trackTintMode
+     * @see #getTrackTintMode()
+     * @see Drawable#setTintMode(PorterDuff.Mode)
+     */
+    public void setTrackTintMode(@Nullable PorterDuff.Mode tintMode) {
+        mTrackTintMode = tintMode;
+        mHasTrackTintMode = true;
+
+        applyTrackTint();
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the track
+     *         drawable
+     * @attr ref android.R.styleable#Switch_trackTintMode
+     * @see #setTrackTintMode(PorterDuff.Mode)
+     */
+    @Nullable
+    public PorterDuff.Mode getTrackTintMode() {
+        return mTrackTintMode;
+    }
+
+    private void applyTrackTint() {
+        if (mTrackDrawable != null && (mHasTrackTint || mHasTrackTintMode)) {
+            mTrackDrawable = mTrackDrawable.mutate();
+
+            if (mHasTrackTint) {
+                mTrackDrawable.setTintList(mTrackTintList);
+            }
+
+            if (mHasTrackTintMode) {
+                mTrackDrawable.setTintMode(mTrackTintMode);
+            }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mTrackDrawable.isStateful()) {
+                mTrackDrawable.setState(getDrawableState());
+            }
+        }
+    }
+
+    /**
      * Set the drawable used for the switch "thumb" - the piece that the user
      * can physically touch and drag along the track.
      *
@@ -516,6 +610,86 @@
     }
 
     /**
+     * Applies a tint to the thumb drawable. Does not modify the current
+     * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+     * <p>
+     * Subsequent calls to {@link #setThumbDrawable(Drawable)} will
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#Switch_thumbTint
+     * @see #getThumbTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    public void setThumbTintList(@Nullable ColorStateList tint) {
+        mThumbTintList = tint;
+        mHasThumbTint = true;
+
+        applyThumbTint();
+    }
+
+    /**
+     * @return the tint applied to the thumb drawable
+     * @attr ref android.R.styleable#Switch_thumbTint
+     * @see #setThumbTintList(ColorStateList)
+     */
+    @Nullable
+    public ColorStateList getThumbTintList() {
+        return mThumbTintList;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setThumbTintList(ColorStateList)}} to the thumb drawable.
+     * The default mode is {@link PorterDuff.Mode#SRC_IN}.
+     *
+     * @param tintMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#Switch_thumbTintMode
+     * @see #getThumbTintMode()
+     * @see Drawable#setTintMode(PorterDuff.Mode)
+     */
+    public void setThumbTintMode(@Nullable PorterDuff.Mode tintMode) {
+        mThumbTintMode = tintMode;
+        mHasThumbTintMode = true;
+
+        applyThumbTint();
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the thumb
+     *         drawable
+     * @attr ref android.R.styleable#Switch_thumbTintMode
+     * @see #setThumbTintMode(PorterDuff.Mode)
+     */
+    @Nullable
+    public PorterDuff.Mode getThumbTintMode() {
+        return mThumbTintMode;
+    }
+
+    private void applyThumbTint() {
+        if (mThumbDrawable != null && (mHasThumbTint || mHasThumbTintMode)) {
+            mThumbDrawable = mThumbDrawable.mutate();
+
+            if (mHasThumbTint) {
+                mThumbDrawable.setTintList(mThumbTintList);
+            }
+
+            if (mHasThumbTintMode) {
+                mThumbDrawable.setTintMode(mThumbTintMode);
+            }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mThumbDrawable.isStateful()) {
+                mThumbDrawable.setState(getDrawableState());
+            }
+        }
+    }
+
+    /**
      * Specifies whether the track should be split by the thumb. When true,
      * the thumb's optical bounds will be clipped out of the track drawable,
      * then the thumb will be drawn into the resulting gap.
@@ -1181,18 +1355,31 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(Switch.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return Switch.class.getName();
+    }
+
+    @Override
+    public void onProvideAssistData(ViewAssistData data, Bundle extras) {
+        super.onProvideAssistData(data, extras);
+        CharSequence switchText = isChecked() ? mTextOn : mTextOff;
+        if (!TextUtils.isEmpty(switchText)) {
+            CharSequence oldText = data.getText();
+            if (TextUtils.isEmpty(oldText)) {
+                data.setText(switchText);
+            } else {
+                StringBuilder newText = new StringBuilder();
+                newText.append(oldText).append(' ').append(switchText);
+                data.setText(newText);
+            }
+        }
     }
 
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(Switch.class.getName());
         CharSequence switchText = isChecked() ? mTextOn : mTextOff;
         if (!TextUtils.isEmpty(switchText)) {
             CharSequence oldText = info.getText();
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 3c3389a..bf35cf9 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -384,18 +384,9 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(TabHost.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(TabHost.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return TabHost.class.getName();
     }
 
     public void setCurrentTab(int index) {
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index bddee91..88ecb13 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -415,11 +415,15 @@
         return false;
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return TabWidget.class.getName();
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(TabWidget.class.getName());
         event.setItemCount(getTabCount());
         event.setCurrentItemIndex(mSelectedTab);
     }
@@ -436,13 +440,6 @@
         super.sendAccessibilityEventUncheckedInternal(event);
     }
 
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(TabWidget.class.getName());
-    }
-
     /**
      * Sets the current tab and focuses the UI on it.
      * This method makes sure that the focused tab matches the selected
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index a6b78a4..c825d17 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -666,18 +666,9 @@
         return new LayoutParams(p);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(TableLayout.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(TableLayout.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return TableLayout.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index c29296a..72fce3f 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -379,18 +379,9 @@
         return new LayoutParams(p);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(TableRow.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(TableRow.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return TableRow.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/TextSwitcher.java b/core/java/android/widget/TextSwitcher.java
index 7c883ba..22822b1 100644
--- a/core/java/android/widget/TextSwitcher.java
+++ b/core/java/android/widget/TextSwitcher.java
@@ -91,17 +91,8 @@
         ((TextView)getCurrentView()).setText(text);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(TextSwitcher.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(TextSwitcher.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return TextSwitcher.class.getName();
     }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 94fc9e9..848c1c0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -109,6 +109,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewAssistData;
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup.LayoutParams;
@@ -8531,12 +8532,26 @@
                 UserHandle.USER_CURRENT_OR_SELF) == 1);
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return TextView.class.getName();
+    }
+
+    @Override
+    public void onProvideAssistData(ViewAssistData data, Bundle extras) {
+        super.onProvideAssistData(data, extras);
+        final boolean isPassword = hasPasswordTransformationMethod();
+        if (!isPassword) {
+            data.setText(getText(), getSelectionStart(), getSelectionEnd());
+        }
+        data.setHint(getHint());
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
 
-        event.setClassName(TextView.class.getName());
         final boolean isPassword = hasPasswordTransformationMethod();
         event.setPassword(isPassword);
 
@@ -8552,7 +8567,6 @@
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
 
-        info.setClassName(TextView.class.getName());
         final boolean isPassword = hasPasswordTransformationMethod();
         info.setPassword(isPassword);
 
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index bbf5f53..9df8a21 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -195,33 +195,17 @@
         mDelegate.onRestoreInstanceState(ss);
     }
 
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return TimePicker.class.getName();
+    }
+
     /** @hide */
     @Override
     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         return mDelegate.dispatchPopulateAccessibilityEvent(event);
     }
 
-    /** @hide */
-    @Override
-    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onPopulateAccessibilityEventInternal(event);
-        mDelegate.onPopulateAccessibilityEvent(event);
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        mDelegate.onInitializeAccessibilityEvent(event);
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        mDelegate.onInitializeAccessibilityNodeInfo(info);
-    }
-
     /**
      * A delegate interface that defined the public API of the TimePicker. Allows different
      * TimePicker implementations. This would need to be implemented by the TimePicker delegates
@@ -252,8 +236,6 @@
 
         boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
         void onPopulateAccessibilityEvent(AccessibilityEvent event);
-        void onInitializeAccessibilityEvent(AccessibilityEvent event);
-        void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
     }
 
     /**
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 1534429..05c7a5f 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -466,16 +466,6 @@
         event.getText().add(selectedDate);
     }
 
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        event.setClassName(TimePicker.class.getName());
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        info.setClassName(TimePicker.class.getName());
-    }
-
     /**
      * Set whether in keyboard mode or not.
      *
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index e162f4a..af69110 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -427,16 +427,6 @@
         event.getText().add(selectedDateUtterance);
     }
 
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        event.setClassName(TimePicker.class.getName());
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        info.setClassName(TimePicker.class.getName());
-    }
-
     private void updateInputState() {
         // Make sure that if the user changes the value and the IME is active
         // for one of the inputs if this widget, the IME is closed. If the user
diff --git a/core/java/android/widget/ToggleButton.java b/core/java/android/widget/ToggleButton.java
index 1b23778..4f8342b 100644
--- a/core/java/android/widget/ToggleButton.java
+++ b/core/java/android/widget/ToggleButton.java
@@ -153,17 +153,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ToggleButton.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ToggleButton.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ToggleButton.class.getName();
     }
 }
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index 9035dbe..0cd7eb9 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -93,17 +93,8 @@
         return mText2;
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(TwoLineListItem.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(TwoLineListItem.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return TwoLineListItem.class.getName();
     }
 }
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index a240dc2..48283d4 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -201,18 +201,9 @@
         setMeasuredDimension(width, height);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(VideoView.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(VideoView.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return VideoView.class.getName();
     }
 
     public int resolveAdjustedSize(int desiredSize, int measureSpec) {
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index d31754b..5ef5222 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -357,17 +357,8 @@
         return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ViewAnimator.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ViewAnimator.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ViewAnimator.class.getName();
     }
 }
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index 587f469..a43a185 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -149,18 +149,9 @@
         updateRunning();
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ViewFlipper.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ViewFlipper.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ViewFlipper.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/ViewSwitcher.java b/core/java/android/widget/ViewSwitcher.java
index c97770f..2f544cc 100644
--- a/core/java/android/widget/ViewSwitcher.java
+++ b/core/java/android/widget/ViewSwitcher.java
@@ -68,18 +68,9 @@
         super.addView(child, index, params);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ViewSwitcher.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ViewSwitcher.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ViewSwitcher.class.getName();
     }
 
     /**
diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java
index e0be0ab..6b3faed 100644
--- a/core/java/android/widget/ZoomButton.java
+++ b/core/java/android/widget/ZoomButton.java
@@ -103,17 +103,8 @@
         return super.dispatchUnhandledMove(focused, direction);
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ZoomButton.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ZoomButton.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ZoomButton.class.getName();
     }
 }
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index a0aacea..bef1ace 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -109,17 +109,8 @@
         return mZoomIn.hasFocus() || mZoomOut.hasFocus();
     }
 
-    /** @hide */
     @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setClassName(ZoomControls.class.getName());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.setClassName(ZoomControls.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ZoomControls.class.getName();
     }
 }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index aba4bd0..c9b44be 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -800,7 +800,12 @@
             if (args.niceName != null) {
                 String property = "wrap." + args.niceName;
                 if (property.length() > 31) {
-                    property = property.substring(0, 31);
+                    // Properties with a trailing "." are illegal.
+                    if (property.charAt(30) != '.') {
+                        property = property.substring(0, 31);
+                    } else {
+                        property = property.substring(0, 30);
+                    }
                 }
                 args.invokeWith = SystemProperties.get(property);
                 if (args.invokeWith != null && args.invokeWith.length() == 0) {
diff --git a/core/java/com/android/internal/transition/EpicenterClipReveal.java b/core/java/com/android/internal/transition/EpicenterClipReveal.java
new file mode 100644
index 0000000..d8a7f16
--- /dev/null
+++ b/core/java/com/android/internal/transition/EpicenterClipReveal.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.transition;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.RectEvaluator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.transition.TransitionValues;
+import android.transition.Visibility;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * EpicenterClipReveal captures the {@link View#getClipBounds()} before and
+ * after the scene change and animates between those and the epicenter bounds
+ * during a visibility transition.
+ */
+public class EpicenterClipReveal extends Visibility {
+    private static final String PROPNAME_CLIP = "android:epicenterReveal:clip";
+    private static final String PROPNAME_BOUNDS = "android:epicenterReveal:bounds";
+
+    public EpicenterClipReveal() {}
+
+    public EpicenterClipReveal(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        super.captureStartValues(transitionValues);
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        super.captureEndValues(transitionValues);
+        captureValues(transitionValues);
+    }
+
+    private void captureValues(TransitionValues values) {
+        final View view = values.view;
+        if (view.getVisibility() == View.GONE) {
+            return;
+        }
+
+        final Rect clip = view.getClipBounds();
+        values.values.put(PROPNAME_CLIP, clip);
+
+        if (clip == null) {
+            final Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
+            values.values.put(PROPNAME_BOUNDS, bounds);
+        }
+    }
+
+    @Override
+    public Animator onAppear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (endValues == null) {
+            return null;
+        }
+
+        final Rect start = getEpicenter();
+        final Rect end = getBestRect(endValues);
+
+        // Prepare the view.
+        view.setClipBounds(start);
+
+        return createRectAnimator(view, start, end);
+    }
+
+    @Override
+    public Animator onDisappear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (startValues == null) {
+            return null;
+        }
+
+        final Rect start = getBestRect(startValues);
+        final Rect end = getEpicenter();
+
+        // Prepare the view.
+        view.setClipBounds(start);
+
+        return createRectAnimator(view, start, end);
+    }
+
+    private Rect getBestRect(TransitionValues values) {
+        final Rect clipRect = (Rect) values.values.get(PROPNAME_CLIP);
+        if (clipRect == null) {
+            return (Rect) values.values.get(PROPNAME_BOUNDS);
+        }
+        return clipRect;
+    }
+
+    private Animator createRectAnimator(View view, Rect start, Rect end) {
+        final RectEvaluator evaluator = new RectEvaluator(new Rect());
+        return ObjectAnimator.ofObject(view, "clipBounds", evaluator, start, end);
+    }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ec01703..90821dc 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -18,7 +18,6 @@
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.ComponentName;
@@ -37,18 +36,12 @@
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
-import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.View;
-import android.widget.Button;
 
-import com.android.internal.R;
 import com.google.android.collect.Lists;
 
 import java.nio.charset.StandardCharsets;
-import libcore.util.HexEncoding;
-
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
@@ -56,6 +49,8 @@
 import java.util.Collection;
 import java.util.List;
 
+import libcore.util.HexEncoding;
+
 /**
  * Utilities for the lock pattern and its settings.
  */
@@ -100,6 +95,11 @@
     public static final int MIN_LOCK_PATTERN_SIZE = 4;
 
     /**
+     * The minimum size of a valid password.
+     */
+    public static final int MIN_LOCK_PASSWORD_SIZE = 4;
+
+    /**
      * The minimum number of dots the user must include in a wrong pattern
      * attempt for it to be counted against the counts that affect
      * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
@@ -489,8 +489,9 @@
      */
     public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) {
         try {
-            if (pattern == null) {
-                throw new IllegalArgumentException("pattern must not be null");
+            if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
+                throw new IllegalArgumentException("pattern must not be null and at least "
+                        + MIN_LOCK_PATTERN_SIZE + " dots long.");
             }
 
             getLockSettings().setLockPattern(patternToString(pattern), userId);
@@ -701,8 +702,9 @@
     public void saveLockPassword(String password, int quality, int userHandle) {
         try {
             DevicePolicyManager dpm = getDevicePolicyManager();
-            if (TextUtils.isEmpty(password)) {
-                throw new IllegalArgumentException("password must not be null nor empty");
+            if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
+                throw new IllegalArgumentException("password must not be null and at least "
+                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
             }
 
             getLockSettings().setLockPassword(password, userHandle);
@@ -1070,21 +1072,6 @@
         return deadline;
     }
 
-    public boolean isEmergencyCallCapable() {
-        return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_voice_capable);
-    }
-
-    public boolean isPukUnlockScreenEnable() {
-        return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_enable_puk_unlock_screen);
-    }
-
-    public boolean isEmergencyCallEnabledWhileSimLocked() {
-        return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
-    }
-
     private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
         try {
             return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
@@ -1136,58 +1123,6 @@
         }
     }
 
-    /**
-     * Sets the emergency button visibility based on isEmergencyCallCapable().
-     *
-     * If the emergency button is visible, sets the text on the emergency button
-     * to indicate what action will be taken.
-     *
-     * If there's currently a call in progress, the button will take them to the call
-     * @param button The button to update
-     * @param shown Indicates whether the given screen wants the emergency button to show at all
-     * @param showIcon Indicates whether to show a phone icon for the button.
-     */
-    public void updateEmergencyCallButtonState(Button button, boolean shown, boolean showIcon) {
-        if (isEmergencyCallCapable() && shown) {
-            button.setVisibility(View.VISIBLE);
-        } else {
-            button.setVisibility(View.GONE);
-            return;
-        }
-
-        int textId;
-        if (isInCall()) {
-            // show "return to call" text and show phone icon
-            textId = R.string.lockscreen_return_to_call;
-            int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
-            button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
-        } else {
-            textId = R.string.lockscreen_emergency_call;
-            int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0;
-            button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
-        }
-        button.setText(textId);
-    }
-
-    /**
-     * Resumes a call in progress. Typically launched from the EmergencyCall button
-     * on various lockscreens.
-     */
-    public void resumeCall() {
-        getTelecommManager().showInCallScreen(false);
-    }
-
-    /**
-     * @return {@code true} if there is a call currently in progress, {@code false} otherwise.
-     */
-    public boolean isInCall() {
-        return getTelecommManager().isInCall();
-    }
-
-    private TelecomManager getTelecommManager() {
-        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
-    }
-
     public void setPowerButtonInstantlyLocks(boolean enabled) {
         setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, getCurrentOrCallingUserId());
     }
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 4e48454..01e835b 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -593,15 +593,13 @@
     }
 
     @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        event.setClassName(ResolverDrawerLayout.class.getName());
+    public CharSequence getAccessibilityClassName() {
+        return ResolverDrawerLayout.class.getName();
     }
 
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        info.setClassName(ResolverDrawerLayout.class.getName());
         if (isEnabled()) {
             if (mCollapseOffset != 0) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index a306697..825fcad 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -393,17 +393,9 @@
         }
 
         @Override
-        public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-            super.onInitializeAccessibilityEventInternal(event);
+        public CharSequence getAccessibilityClassName() {
             // This view masquerades as an action bar tab.
-            event.setClassName(ActionBar.Tab.class.getName());
-        }
-
-        @Override
-        public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-            super.onInitializeAccessibilityNodeInfoInternal(info);
-            // This view masquerades as an action bar tab.
-            info.setClassName(ActionBar.Tab.class.getName());
+            return ActionBar.Tab.class.getName();
         }
 
         @Override
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index 2f987e9..a206e7f 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -148,6 +148,7 @@
         mHasMeasurements = false;
 
         requestLayout();
+        invalidate();
     }
 
     public void setForegroundColor(int color) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index cb9b421..1dd10e1 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -87,6 +87,7 @@
     android_graphics_Canvas.cpp \
     android_graphics_Picture.cpp \
     android/graphics/AutoDecodeCancel.cpp \
+    android/graphics/AvoidXfermode.cpp \
     android/graphics/Bitmap.cpp \
     android/graphics/BitmapFactory.cpp \
     android/graphics/Camera.cpp \
diff --git a/core/jni/android/graphics/AvoidXfermode.cpp b/core/jni/android/graphics/AvoidXfermode.cpp
new file mode 100644
index 0000000..9ca1f26
--- /dev/null
+++ b/core/jni/android/graphics/AvoidXfermode.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "AvoidXfermode.h"
+#include "SkColorPriv.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+#include "SkString.h"
+
+AvoidXfermode::AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) {
+    if (tolerance > 255) {
+        tolerance = 255;
+    }
+    fTolerance = SkToU8(tolerance);
+    fOpColor = opColor;
+    fDistMul = (256 << 14) / (tolerance + 1);
+    fMode = mode;
+}
+
+SkFlattenable* AvoidXfermode::CreateProc(SkReadBuffer& buffer) {
+    const SkColor color = buffer.readColor();
+    const unsigned tolerance = buffer.readUInt();
+    const unsigned mode = buffer.readUInt();
+    return Create(color, tolerance, (Mode)mode);
+}
+
+void AvoidXfermode::flatten(SkWriteBuffer& buffer) const {
+    buffer.writeColor(fOpColor);
+    buffer.writeUInt(fTolerance);
+    buffer.writeUInt(fMode);
+}
+
+// returns 0..31
+static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) {
+    SkASSERT(r <= SK_R16_MASK);
+    SkASSERT(g <= SK_G16_MASK);
+    SkASSERT(b <= SK_B16_MASK);
+
+    unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
+    unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
+    unsigned db = SkAbs32(SkGetPackedB16(c) - b);
+
+    return SkMax32(dr, SkMax32(dg, db));
+}
+
+// returns 0..255
+static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) {
+    SkASSERT(r <= 0xFF);
+    SkASSERT(g <= 0xFF);
+    SkASSERT(b <= 0xFF);
+
+    unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
+    unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
+    unsigned db = SkAbs32(SkGetPackedB32(c) - b);
+
+    return SkMax32(dr, SkMax32(dg, db));
+}
+
+static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) {
+    int tmp = dist * mul - sub;
+    int result = (tmp + (1 << 13)) >> 14;
+
+    return result;
+}
+
+static inline unsigned Accurate255To256(unsigned x) {
+    return x + (x >> 7);
+}
+
+void AvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                             const SkAlpha aa[]) const {
+    unsigned    opR = SkColorGetR(fOpColor);
+    unsigned    opG = SkColorGetG(fOpColor);
+    unsigned    opB = SkColorGetB(fOpColor);
+    uint32_t    mul = fDistMul;
+    uint32_t    sub = (fDistMul - (1 << 14)) << 8;
+
+    int MAX, mask;
+
+    if (kTargetColor_Mode == fMode) {
+        mask = -1;
+        MAX = 255;
+    } else {
+        mask = 0;
+        MAX = 0;
+    }
+
+    for (int i = 0; i < count; i++) {
+        int d = color_dist32(dst[i], opR, opG, opB);
+        // now reverse d if we need to
+        d = MAX + (d ^ mask) - mask;
+        SkASSERT((unsigned)d <= 255);
+        d = Accurate255To256(d);
+
+        d = scale_dist_14(d, mul, sub);
+        SkASSERT(d <= 256);
+
+        if (d > 0) {
+            if (aa) {
+                d = SkAlphaMul(d, Accurate255To256(*aa++));
+                if (0 == d) {
+                    continue;
+                }
+            }
+            dst[i] = SkFourByteInterp256(src[i], dst[i], d);
+        }
+    }
+}
+
+static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) {
+    SkASSERT(scale <= 32);
+    scale <<= 3;
+
+    return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale),
+                        SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale),
+                        SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale));
+}
+
+void AvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                             const SkAlpha aa[]) const {
+    unsigned    opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS);
+    unsigned    opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS);
+    unsigned    opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS);
+    uint32_t    mul = fDistMul;
+    uint32_t    sub = (fDistMul - (1 << 14)) << SK_R16_BITS;
+
+    int MAX, mask;
+
+    if (kTargetColor_Mode == fMode) {
+        mask = -1;
+        MAX = 31;
+    } else {
+        mask = 0;
+        MAX = 0;
+    }
+
+    for (int i = 0; i < count; i++) {
+        int d = color_dist16(dst[i], opR, opG, opB);
+        // now reverse d if we need to
+        d = MAX + (d ^ mask) - mask;
+        SkASSERT((unsigned)d <= 31);
+        // convert from 0..31 to 0..32
+        d += d >> 4;
+        d = scale_dist_14(d, mul, sub);
+        SkASSERT(d <= 32);
+
+        if (d > 0) {
+            if (aa) {
+                d = SkAlphaMul(d, Accurate255To256(*aa++));
+                if (0 == d) {
+                    continue;
+                }
+            }
+            dst[i] = SkBlend3216(src[i], dst[i], d);
+        }
+    }
+}
+
+void AvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+        const SkAlpha aa[]) const {
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void AvoidXfermode::toString(SkString* str) const {
+    str->append("AvoidXfermode: opColor: ");
+    str->appendHex(fOpColor);
+    str->appendf("distMul: %d ", fDistMul);
+
+    static const char* gModeStrings[] = { "Avoid", "Target" };
+
+    str->appendf("mode: %s", gModeStrings[fMode]);
+}
+#endif
diff --git a/core/jni/android/graphics/AvoidXfermode.h b/core/jni/android/graphics/AvoidXfermode.h
new file mode 100644
index 0000000..318d7be
--- /dev/null
+++ b/core/jni/android/graphics/AvoidXfermode.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef AvoidXfermode_DEFINED
+#define AvoidXfermode_DEFINED
+
+#include "SkColor.h"
+#include "SkTypes.h"
+#include "SkXfermode.h"
+
+/** \class AvoidXfermode
+
+    This xfermode will draw the src everywhere except on top of the specified
+    color.
+*/
+class AvoidXfermode : public SkXfermode {
+public:
+    enum Mode {
+        kAvoidColor_Mode,   //!< draw everywhere except on the opColor
+        kTargetColor_Mode   //!< draw only on top of the opColor
+    };
+
+    /** This xfermode draws, or doesn't draw, based on the destination's
+        distance from an op-color.
+
+        There are two modes, and each mode interprets a tolerance value.
+
+        Avoid: In this mode, drawing is allowed only on destination pixels that
+               are different from the op-color.
+               Tolerance near 0: avoid any colors even remotely similar to the op-color
+               Tolerance near 255: avoid only colors nearly identical to the op-color
+
+        Target: In this mode, drawing only occurs on destination pixels that
+                are similar to the op-color
+                Tolerance near 0: draw only on colors that are nearly identical to the op-color
+                Tolerance near 255: draw on any colors even remotely similar to the op-color
+     */
+    static AvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
+        return SkNEW_ARGS(AvoidXfermode, (opColor, tolerance, mode));
+    }
+
+    // overrides from SkXfermode
+    void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+            const SkAlpha aa[]) const override;
+    void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+            const SkAlpha aa[]) const override;
+    void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+            const SkAlpha aa[]) const override;
+
+    SK_TO_STRING_OVERRIDE()
+    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(AvoidXfermode)
+
+protected:
+    AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode);
+    void flatten(SkWriteBuffer&) const override;
+
+private:
+    SkColor     fOpColor;
+    uint32_t    fDistMul;   // x.14 cached from fTolerance
+    uint8_t     fTolerance;
+    Mode        fMode;
+
+    typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index b572604..036ece1 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -96,7 +96,7 @@
 }
 
 static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
-    SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
+    SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas();
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
     v->applyToCanvas(canvas);
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 9ea63aa..dde1393 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -366,7 +366,7 @@
     if (!canvasHandle) {
         return NULL;
     }
-    SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
+    SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas();
     SkASSERT(c);
     return c;
 }
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 543323c..3f8bfe2 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -120,7 +120,7 @@
     static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
             jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
             jint destDensity, jint srcDensity) {
-        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
+        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
         const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         Res_png_9patch* chunk  = reinterpret_cast<Res_png_9patch*>(chunkHandle);
         const Paint* paint     = reinterpret_cast<Paint*>(paintHandle);
@@ -139,7 +139,7 @@
     static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
             jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
             jint destDensity, jint srcDensity) {
-        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
+        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
         const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         Res_png_9patch* chunk  = reinterpret_cast<Res_png_9patch*>(chunkHandle);
         const Paint* paint     = reinterpret_cast<Paint*>(paintHandle);
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index c249012..12bfaa2 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -101,7 +101,7 @@
     }
     validate();
     if (NULL != mPicture.get()) {
-        mPicture.get()->playback(canvas->getSkCanvas());
+        mPicture.get()->playback(canvas->asSkCanvas());
     }
 }
 
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index 5a3883a..4a424ae 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -18,7 +18,7 @@
 #include "GraphicsJNI.h"
 #include "core_jni_helpers.h"
 
-#include "SkAvoidXfermode.h"
+#include "AvoidXfermode.h"
 #include "SkPixelXorXfermode.h"
 
 namespace android {
@@ -35,8 +35,8 @@
     static jlong avoid_create(JNIEnv* env, jobject, jint opColor,
                                 jint tolerance, jint modeHandle)
     {
-        SkAvoidXfermode::Mode mode = static_cast<SkAvoidXfermode::Mode>(modeHandle);
-        return reinterpret_cast<jlong>(SkAvoidXfermode::Create(opColor, tolerance, mode));
+        AvoidXfermode::Mode mode = static_cast<AvoidXfermode::Mode>(modeHandle);
+        return reinterpret_cast<jlong>(AvoidXfermode::Create(opColor, tolerance, mode));
     }
 
     static jlong pixelxor_create(JNIEnv* env, jobject, jint opColor)
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 0bf269f..ef78fde 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -338,13 +338,15 @@
 }
 
 static jint
-android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
+android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
 {
     const char *c_address = env->GetStringUTFChars(device_address, NULL);
+    const char *c_name = env->GetStringUTFChars(device_name, NULL);
     int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
                                           static_cast <audio_policy_dev_state_t>(state),
-                                          c_address));
+                                          c_address, c_name));
     env->ReleaseStringUTFChars(device_address, c_address);
+    env->ReleaseStringUTFChars(device_name, c_name);
     return (jint) status;
 }
 
@@ -788,10 +790,11 @@
     jintArray jFormats = NULL;
     jobjectArray jGains = NULL;
     jobject jHandle = NULL;
+    jstring jDeviceName = NULL;
     bool useInMask;
 
-    ALOGV("convertAudioPortFromNative id %d role %d type %d",
-                                  nAudioPort->id, nAudioPort->role, nAudioPort->type);
+    ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
+        nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
 
     jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
     if (jSamplingRates == NULL) {
@@ -871,17 +874,21 @@
         goto exit;
     }
 
+    jDeviceName = env->NewStringUTF(nAudioPort->name);
+
     if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
         ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
         jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
         *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
-                                     jHandle, jSamplingRates, jChannelMasks, jFormats, jGains,
+                                     jHandle, jDeviceName,
+                                     jSamplingRates, jChannelMasks, jFormats, jGains,
                                      nAudioPort->ext.device.type, jAddress);
         env->DeleteLocalRef(jAddress);
     } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
         ALOGV("convertAudioPortFromNative is a mix");
         *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
-                                     jHandle, nAudioPort->role, jSamplingRates, jChannelMasks,
+                                     jHandle, nAudioPort->role, jDeviceName,
+                                     jSamplingRates, jChannelMasks,
                                      jFormats, jGains);
     } else {
         ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
@@ -905,6 +912,9 @@
     env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
 
 exit:
+    if (jDeviceName != NULL) {
+        env->DeleteLocalRef(jDeviceName);
+    }
     if (jSamplingRates != NULL) {
         env->DeleteLocalRef(jSamplingRates);
     }
@@ -1496,7 +1506,7 @@
     {"isStreamActiveRemotely","(II)Z",  (void *)android_media_AudioSystem_isStreamActiveRemotely},
     {"isSourceActive",      "(I)Z",     (void *)android_media_AudioSystem_isSourceActive},
     {"newAudioSessionId",   "()I",      (void *)android_media_AudioSystem_newAudioSessionId},
-    {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
+    {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
     {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
     {"setPhoneState",       "(I)I",     (void *)android_media_AudioSystem_setPhoneState},
     {"setForceUse",         "(II)I",    (void *)android_media_AudioSystem_setForceUse},
@@ -1556,7 +1566,7 @@
     jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
     gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
     gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
-            "(Landroid/media/AudioHandle;I[I[I[I[Landroid/media/AudioGain;)V");
+            "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
     gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
                                                "Landroid/media/AudioHandle;");
     gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
@@ -1594,12 +1604,12 @@
     jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
     gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
     gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
-            "(Landroid/media/AudioHandle;[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
+            "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
 
     jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
     gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
     gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
-            "(Landroid/media/AudioHandle;I[I[I[I[Landroid/media/AudioGain;)V");
+            "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
 
     jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
     gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
diff --git a/core/res/res/anim/disabled_anim_material.xml b/core/res/res/anim/disabled_anim_material.xml
deleted file mode 100644
index 6a7731e..0000000
--- a/core/res/res/anim/disabled_anim_material.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false">
-        <set>
-            <objectAnimator android:propertyName="alpha"
-                android:duration="@integer/disabled_alpha_animation_duration"
-                android:valueTo="?attr/disabledAlpha"
-                android:valueType="floatType"/>
-        </set>
-    </item>
-    <item>
-        <set>
-            <objectAnimator android:propertyName="alpha"
-                android:duration="@integer/disabled_alpha_animation_duration"
-                android:valueTo="1"
-                android:valueType="floatType"/>
-        </set>
-    </item>
-</selector>
\ No newline at end of file
diff --git a/core/res/res/color/btn_material_accent.xml b/core/res/res/color/btn_colored_material.xml
similarity index 93%
rename from core/res/res/color/btn_material_accent.xml
rename to core/res/res/color/btn_colored_material.xml
index 71469b6..b45f824 100644
--- a/core/res/res/color/btn_material_accent.xml
+++ b/core/res/res/color/btn_colored_material.xml
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="@color/button_material_dark" />
+          android:color="?attr/colorButtonNormal" />
     <item android:color="?attr/colorAccent" />
 </selector>
diff --git a/core/res/res/color/btn_material_accent.xml b/core/res/res/color/btn_colored_text_material.xml
similarity index 82%
copy from core/res/res/color/btn_material_accent.xml
copy to core/res/res/color/btn_colored_text_material.xml
index 71469b6..950d04a 100644
--- a/core/res/res/color/btn_material_accent.xml
+++ b/core/res/res/color/btn_colored_text_material.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -17,6 +17,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="@color/button_material_dark" />
-    <item android:color="?attr/colorAccent" />
+          android:color="?attr/textColorSecondary" />
+    <item android:color="?attr/colorAccent"/>
 </selector>
diff --git a/core/res/res/drawable-mdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_clear_mtrl_alpha.png
deleted file mode 100644
index d43e4d1..0000000
--- a/core/res/res/drawable-mdpi/ic_clear_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_clear_mtrl_alpha.png
deleted file mode 100644
index ddacb59..0000000
--- a/core/res/res/drawable-xhdpi/ic_clear_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_clear_mtrl_alpha.png
deleted file mode 100644
index 21ed9144..0000000
--- a/core/res/res/drawable-xxhdpi/ic_clear_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_clear_material.xml b/core/res/res/drawable/ic_clear_material.xml
index 076c0a2..a21f47a 100644
--- a/core/res/res/drawable/ic_clear_material.xml
+++ b/core/res/res/drawable/ic_clear_material.xml
@@ -14,6 +14,13 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_clear_mtrl_alpha"
-    android:tint="?attr/colorControlNormal" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
+<path
+    android:pathData="M19,6.41L17.59,5,12,10.59,6.41,5,5,6.41,10.59,12,5,17.59,6.41,19,12,13.41,17.59,19,19,17.59,13.41,12z"
+    android:fillColor="@color/white"/>
+</vector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_material.xml b/core/res/res/drawable/scrubber_progress_horizontal_material.xml
index f2ea30f..89a1787 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_material.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_material.xml
@@ -14,29 +14,35 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false">
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@id/background">
         <nine-patch android:src="@drawable/scrubber_track_mtrl_alpha"
-            android:tint="?attr/colorControlNormal" />
-    </item>
-    <item>
-        <layer-list>
-            <item android:id="@id/background">
-                <nine-patch android:src="@drawable/scrubber_track_mtrl_alpha"
                     android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:id="@id/secondaryProgress">
-                <scale android:scaleWidth="100%">
-                    <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
-                        android:tint="?attr/colorControlNormal" />
-                </scale>
-            </item>
-            <item android:id="@id/progress">
-                <scale android:scaleWidth="100%">
-                    <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
-                        android:tint="?attr/colorControlActivated" />
-                </scale>
-            </item>
-        </layer-list>
     </item>
-</selector>
+    <item android:id="@id/secondaryProgress">
+        <scale android:scaleWidth="100%">
+            <selector>
+                <item android:state_enabled="false">
+                    <color android:color="@color/transparent" />
+                </item>
+                <item>
+                    <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
+                                android:tint="?attr/colorControlNormal" />
+                </item>
+            </selector>
+        </scale>
+    </item>
+    <item android:id="@id/progress">
+        <scale android:scaleWidth="100%">
+            <selector>
+                <item android:state_enabled="false">
+                    <color android:color="@color/transparent" />
+                </item>
+                <item>
+                    <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
+                                android:tint="?attr/colorControlActivated" />
+                </item>
+            </selector>
+        </scale>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/core/res/res/layout/dialog_custom_title_material.xml b/core/res/res/layout/dialog_custom_title_material.xml
index 248a05e..50ed910 100644
--- a/core/res/res/layout/dialog_custom_title_material.xml
+++ b/core/res/res/layout/dialog_custom_title_material.xml
@@ -27,6 +27,8 @@
         android:layout_weight="0"
         android:gravity="center_vertical|start"
         style="?attr/windowTitleBackgroundStyle" />
+    <View android:layout_width="match_parent"
+        android:layout_height="0dp" />
     <FrameLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/dialog_title_icons_material.xml b/core/res/res/layout/dialog_title_icons_material.xml
index 62af096..3866ca7 100644
--- a/core/res/res/layout/dialog_title_icons_material.xml
+++ b/core/res/res/layout/dialog_title_icons_material.xml
@@ -48,6 +48,9 @@
             android:layout_marginStart="8dip" />
     </LinearLayout>
 
+    <View android:layout_width="match_parent"
+        android:layout_height="0dp" />
+
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_material.xml b/core/res/res/layout/dialog_title_material.xml
index 339d569..1ea7f6e 100644
--- a/core/res/res/layout/dialog_title_material.xml
+++ b/core/res/res/layout/dialog_title_material.xml
@@ -32,6 +32,8 @@
         android:paddingStart="?attr/dialogPreferredPadding"
         android:paddingEnd="?attr/dialogPreferredPadding"
         android:paddingTop="@dimen/dialog_padding_top_material" />
+    <View android:layout_width="match_parent"
+        android:layout_height="0dp" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/preference_dialog_edittext_material.xml b/core/res/res/layout/preference_dialog_edittext_material.xml
new file mode 100644
index 0000000..df76f7f
--- /dev/null
+++ b/core/res/res/layout/preference_dialog_edittext_material.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Layout used as the dialog's content View for EditTextPreference. -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginTop="48dp"
+    android:layout_marginBottom="48dp"
+    android:overScrollMode="ifContentScrolls">
+
+    <LinearLayout
+        android:id="@+id/edittext_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="20dp"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/message"
+            android:layout_marginBottom="48dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingStart="4dp"
+            android:paddingEnd="4dp"
+            android:textColor="?attr/textColorSecondary"
+            style="?attr/textAppearanceSmall" />
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/transition/popup_window_enter.xml b/core/res/res/transition/popup_window_enter.xml
new file mode 100644
index 0000000..92d4c1e
--- /dev/null
+++ b/core/res/res/transition/popup_window_enter.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+               android:transitionOrdering="together">
+     <transition class="com.android.internal.transition.EpicenterClipReveal"
+         android:interpolator="@android:interpolator/accelerate_cubic"
+         android:startDelay="50"
+         android:duration="300" />
+     <fade
+         android:interpolator="@android:interpolator/linear"
+         android:duration="100" />
+</transitionSet>
diff --git a/core/res/res/color/btn_material_accent.xml b/core/res/res/transition/popup_window_exit.xml
similarity index 70%
copy from core/res/res/color/btn_material_accent.xml
copy to core/res/res/transition/popup_window_exit.xml
index 71469b6..5cb9f0b 100644
--- a/core/res/res/color/btn_material_accent.xml
+++ b/core/res/res/transition/popup_window_exit.xml
@@ -13,10 +13,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false"
-          android:alpha="?attr/disabledAlpha"
-          android:color="@color/button_material_dark" />
-    <item android:color="?attr/colorAccent" />
-</selector>
+<fade xmlns:android="http://schemas.android.com/apk/res/android"
+      android:interpolator="@android:interpolator/linear" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 415e6d5..4eed141 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 uur gelede"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> uur gelede"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Afgelope <xliff:g id="COUNT">%d</xliff:g> dae"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Verlede maand"</string>
     <string name="older" msgid="5211975022815554840">"Ouer"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android begin tans …"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimeer tans berging."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimeer program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Begin programme."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Voltooi herlaai."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> loop"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kon nie aan Wi-Fikoppel nie"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" het \'n swak internetverbinding."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Laat verbinding toe?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s wil graag koppel aan %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"\'n Program"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Begin Wi-Fi Direct. Dit sal die Wi-Fi-kliënt/warmkol afskakel."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-versoek is gewysig tot DIAL-versoek."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-versoek is gewysig tot USSD-versoek."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-versoek is gewysig tot nuwe SS-versoek."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index aafffe8..036abe1 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"ከ1 ሰዓት በፊት"</item>
     <item quantity="other" msgid="2467273239587587569">"ከ <xliff:g id="COUNT">%d</xliff:g> ሰዓት በፊት"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"ቀኖች <xliff:g id="COUNT">%d</xliff:g> ያልቃል"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">" ያለፈው ወር"</string>
     <string name="older" msgid="5211975022815554840">"የድሮ"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android በመጀመር ላይ ነው…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ማከማቻን በማመቻቸት ላይ።"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"መተግበሪያዎች በአግባቡ በመጠቀም ላይ <xliff:g id="NUMBER_0">%1$d</xliff:g> ከ <xliff:g id="NUMBER_1">%2$d</xliff:g> ፡፡"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ን ማዘጋጀት።"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"መተግበሪያዎችን በማስጀመር ላይ፡፡"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"አጨራረስ ማስነሻ፡፡"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> አሂድ"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ወደ Wi-Fi ለማያያዝ አልተቻለም"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ደካማ የበይነመረብ ግንኙነት ኣለው።"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ግንኙነት ይፈቀድ?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ከ%2$s ጋር መገናኘት ይፈልጋል"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"መተግበሪያ %1$s ወደ Wifi Network %2$s መገናኘት ይፈልጋል"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"አንድ መተግበሪያ"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ቀጥታ"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"የWi-Fi በቀጥታ  ጀምር።ይህ የWi-Fi ደንበኛ /ድረስ ነጥብ  ያጠፋል።"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS ጥያቄ ወደ ደውል ጥያቄ ተሻሽሎዋል።"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS ጥያቄ ወደ USSD ጥያቄ ተሻሽሎዋል።"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS ጥያቄ ወደ አዲስ SS ጥያቄ ተሻሽሎዋል።"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB Peripheral ወደብ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 63340fc..2a4c65c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"قبل ساعة واحدة"</item>
     <item quantity="other" msgid="2467273239587587569">"قبل <xliff:g id="COUNT">%d</xliff:g> ساعات"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"آخر <xliff:g id="COUNT">%d</xliff:g> من الأيام"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"الشهر الماضي"</string>
     <string name="older" msgid="5211975022815554840">"أقدم"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"‏جارٍ تشغيل Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"جارٍ تحسين السعة التخزينية."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"جارٍ تحسين التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"بدء التطبيقات."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"جارٍ إعادة التشغيل."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> يعمل"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏تعذر الاتصال بـ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" لديها اتصال إنترنت رديء."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"هل تريد السماح بالاتصال؟"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"‏%1$s يرغب في الاتصال بـ %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"تطبيق"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"‏اتصال Wi-Fi مباشر"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"‏ابدأ Wi-Fi Direct. يؤدي هذا إلى إيقاف عميل/نقطة اتصال Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"‏يتم تعديل الطلب SS لطلب الاتصال."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"‏يتم تعديل طلب SS إلى طلب USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"‏يتم تعديل طلب SS إلى طلب SS الجديد."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 2112d8a..0808af8 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Преди 1 час"</item>
     <item quantity="other" msgid="2467273239587587569">"Преди <xliff:g id="COUNT">%d</xliff:g> часа"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Последните <xliff:g id="COUNT">%d</xliff:g> дни"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Последният месец"</string>
     <string name="older" msgid="5211975022815554840">"По-стари"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android се стартира…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Хранилището се оптимизира."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизира се приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Приложенията се стартират."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Зареждането завършва."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> се изпълнява"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можа да се свърже с Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лоша връзка с интернет."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Да се разреши ли връзката?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s иска да установи връзка с/ъс %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Приложение"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Стартиране на Wi-Fi Direct. Това ще изключи клиентската програма/точката за достъп до Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS заявката е променена на DIAL заявка."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS заявката е променена на USSD заявка."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS заявката е променена на нова SS заявка."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index f37b7fb..bc61458 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"১ ঘন্টা আগে"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ঘন্টা আগে"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"গত <xliff:g id="COUNT">%d</xliff:g> দিনে"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"গত মাস"</string>
     <string name="older" msgid="5211975022815554840">"পুরোনো"</string>
   <plurals name="num_days_ago">
@@ -1259,7 +1257,7 @@
     <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="dialog_alert_title" msgid="2049658708609043103">"খেয়াল করুন"</string>
     <string name="loading" msgid="7933681260296021180">"লোড হচ্ছে..."</string>
     <string name="capital_on" msgid="1544682755514494298">"চালু করুন"</string>
     <string name="capital_off" msgid="6815870386972805832">"বন্ধ করুন"</string>
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android চালু হচ্ছে…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"সঞ্চয়স্থান অপ্টিমাইজ করা হচ্ছে৷"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান অপ্টিমাইজ করা হচ্ছে৷"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> প্রস্তুত করা হচ্ছে৷"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"অ্যাপ্লিকেশানগুলি শুরু করা হচ্ছে৷"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"চালু করা সম্পূর্ণ হচ্ছে৷"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> চলছে"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi এর সাথে সংযোগ করা যায়নি"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" একটি দুর্বল ইন্টারনেট সংযোগ রয়েছে৷"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"সংযোগের মঞ্জুরি দেবেন?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s %2$s এর সাথে সংযোগ করতে চায়"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"অ্যাপ্লিকেশান %1$s Wifi নেটওয়ার্ক %2$s এর সাথে সংযোগ করতে চায়"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"একটি অ্যাপ্লিকেশান"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ডাইরেক্ট"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi ডাইরেক্ট আরম্ভ করুন৷ এটি Wi-Fi client/hotspot কে বন্ধ করবে৷"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS অনুরোধটিকে ডায়াল অনুরোধে রুপান্তরিত করা হয়েছে৷"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS অনুরোধটিকে নতুন USSD অনুরোধে রুপান্তরিত করা হয়েছে৷"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS অনুরোধটিকে নতুন SS অনুরোধে রুপান্তরিত করা হয়েছে৷"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB পেরিফেরাল পোর্ট"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index a2235fd..2a087b5 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Fa 1 hora"</item>
     <item quantity="other" msgid="2467273239587587569">"Fa <xliff:g id="COUNT">%d</xliff:g> hores"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Els darrers <xliff:g id="COUNT">%d</xliff:g> dies"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"El mes passat"</string>
     <string name="older" msgid="5211975022815554840">"Més antigues"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"S\'està iniciant Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"S\'està optimitzant l\'emmagatzematge."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"S\'està optimitzant l\'aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"S\'està preparant <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"S\'estan iniciant les aplicacions."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"S\'està finalitzant l\'actualització."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> s\'està executant"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No s\'ha pogut connectar a la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" té una mala connexió a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vols permetre la connexió?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s vol connectar amb %2$s."</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"L\'aplicació %1$s vol connectar-se a la xarxa Wi-Fi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Una aplicació"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Inicia Wi-Fi Direct. Això desactivarà el client/la zona Wi-Fi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"La sol·licitud SS s\'ha transformat en una sol·licitud DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"La sol·licitud SS s\'ha transformat en una sol·licitud USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"La sol·licitud SS s\'ha transformat en una sol·licitud SS nova."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Port perifèric USB"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index dc9eda2..8e485bd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"před 1 h"</item>
     <item quantity="other" msgid="2467273239587587569">"před <xliff:g id="COUNT">%d</xliff:g> h"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Posledních <xliff:g id="COUNT">%d</xliff:g> dnů"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Poslední měsíc"</string>
     <string name="older" msgid="5211975022815554840">"Starší"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Spouštění systému Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Probíhá optimalizace úložiště."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Spouštění aplikací."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Dokončování inicializace."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Běží aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Připojení k síti Wi-Fi se nezdařilo"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má pomalé připojení k internetu."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Povolit připojení?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s se chce připojit k %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikace"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Přímé připojení sítě Wi-Fi"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Spustit přímé připojení sítě Wi-Fi. Tato možnost vypne provoz sítě Wi-Fi v režimu klient/hotspot."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Požadavek SS byl změněn na požadavek DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Požadavek SS byl změněn na požadavek USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Požadavek SS byl změněn na nový požadavek SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 1a412c1..bdb65a9 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"for 1 time siden"</item>
     <item quantity="other" msgid="2467273239587587569">"for <xliff:g id="COUNT">%d</xliff:g> timer siden"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Seneste <xliff:g id="COUNT">%d</xliff:g> dage"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Seneste måned"</string>
     <string name="older" msgid="5211975022815554840">"Ældre"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android starter..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Lageret optimeres."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerer app <xliff:g id="NUMBER_0">%1$d</xliff:g> ud af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Åbner dine apps."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Gennemfører start."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> er i gang"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kunne ikke oprette forbindelse til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig internetforbindelse."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vil du tillade denne forbindelse?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s vil gerne oprette forbindelse til %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Applikationen %1$s vil gerne have forbindelse til Wi-Fi-netværk %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"En applikation"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. Dette slår Wi-Fi-klient/hotspot fra."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-anmodningen er ændret til en DIAL-anmodning."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-anmodningen er ændret til en USSD-anmodning."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-anmodningen er ændret til en ny SS-anmodning."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Ydre USB-port"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 56dd21e..14717c0 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"vor 1 Stunde"</item>
     <item quantity="other" msgid="2467273239587587569">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Letzte <xliff:g id="COUNT">%d</xliff:g> Tage"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Letzter Monat"</string>
     <string name="older" msgid="5211975022815554840">"Älter"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android wird gestartet…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Speicher wird optimiert"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g> wird optimiert..."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Apps werden gestartet..."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Start wird abgeschlossen..."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> läuft"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Es konnte keine WLAN-Verbindung hergestellt werden."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" hat eine schlechte Internetverbindung."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Verbindung zulassen?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s möchte eine Verbindung mit %2$s herstellen."</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Eine App"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct-Betrieb starten. Hierdurch wird der WLAN-Client-/-Hotspot-Betrieb deaktiviert."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-Anfrage wird in DIAL-Anfrage geändert."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-Anfrage wird in USSD-Anfrage geändert."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-Anfrage wird in neue SS-Anfrage geändert."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 737cc1f..94d16cf 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -42,10 +42,10 @@
     <string name="untitled" msgid="4638956954852782576">"&lt;Χωρίς τίτλο&gt;"</string>
     <string name="emptyPhoneNumber" msgid="7694063042079676517">"(Δεν υπάρχει τηλεφωνικός αριθμός)"</string>
     <string name="unknownName" msgid="6867811765370350269">"Άγνωστο"</string>
-    <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Αυτόματος τηλεφωνητής"</string>
+    <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Αυτ/τος τηλεφωνητής"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Πρόβλημα σύνδεσης ή μη έγκυρος κώδικας MMI."</string>
-    <string name="mmiFdnError" msgid="5224398216385316471">"Η λειτουργία περιορίζεται μόνο σε καθορισμένους αριθμούς κλήσης."</string>
+    <string name="mmiFdnError" msgid="5224398216385316471">"Η λειτουργία περιορίζεται μόνο σε προκαθορισμένους αριθμούς κλήσης."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Η υπηρεσία ενεργοποιήθηκε."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Η υπηρεσία ενεργοποιήθηκε για:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Η υπηρεσία έχει απενεργοποιηθεί."</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"πριν από 1 ώρα"</item>
     <item quantity="other" msgid="2467273239587587569">"πριν από <xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Τελευταίες <xliff:g id="COUNT">%d</xliff:g> ημέρες"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Τελευταίος μήνας"</string>
     <string name="older" msgid="5211975022815554840">"Παλαιότερα"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Εκκίνηση Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Βελτιστοποίηση αποθηκευτικού χώρου."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Βελτιστοποίηση της εφαρμογής <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Προετοιμασία <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Έναρξη εφαρμογών."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Ολοκλήρωση εκκίνησης."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> εκτελείται"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Δεν είναι δυνατή η σύνδεση στο Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" έχει κακή σύνδεση στο Διαδίκτυο."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Να επιτρέπεται η σύνδεση;"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s θα ήθελε να συνδεθεί με %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Η εφαρμογή %1$s θα ήθελε να συνδεθεί με το δίκτυο WiFi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Μια εφαρμογή"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Ξεκινήστε τη λειτουργία Wi-Fi Direct. Θα απενεργοποιηθεί η λειτουργία πελάτη/φορητού σημείου πρόσβασης Wi-Fi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Το αίτημα SS τροποποιήθηκε σε αίτημα DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Το αίτημα SS τροποποιήθηκε σε αίτημα USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Το αίτημα SS τροποποιήθηκε σε νέο αίτημα SS."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Περιφερειακή θύρα USB"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index df8b41f..643e190 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 hour ago"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> hours ago"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Last <xliff:g id="COUNT">%d</xliff:g> days"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Last month"</string>
     <string name="older" msgid="5211975022815554840">"Older"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android is starting…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Finishing boot."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Allow connection?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s would like to connect to %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Application %1$s would like to connect to Wi-Fi Network %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"An application"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS request is modified to DIAL request."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS request is modified to USSD request."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS request is modified to new SS request."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB Peripheral Port"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index df8b41f..643e190 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 hour ago"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> hours ago"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Last <xliff:g id="COUNT">%d</xliff:g> days"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Last month"</string>
     <string name="older" msgid="5211975022815554840">"Older"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android is starting…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Finishing boot."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Allow connection?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s would like to connect to %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Application %1$s would like to connect to Wi-Fi Network %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"An application"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS request is modified to DIAL request."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS request is modified to USSD request."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS request is modified to new SS request."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB Peripheral Port"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index a9353db..a35ad8d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1139,17 +1139,15 @@
     <item quantity="other" msgid="2176942008915455116">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
   </plurals>
   <plurals name="num_hours_ago">
-    <item quantity="one" msgid="9150797944610821849">"Hace 1 hora."</item>
-    <item quantity="other" msgid="2467273239587587569">"Hace <xliff:g id="COUNT">%d</xliff:g> horas."</item>
+    <item quantity="one" msgid="9150797944610821849">"Hace 1 hora"</item>
+    <item quantity="other" msgid="2467273239587587569">"Hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Últimos <xliff:g id="COUNT">%d</xliff:g> días"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Último mes"</string>
     <string name="older" msgid="5211975022815554840">"Antiguos"</string>
   <plurals name="num_days_ago">
     <item quantity="one" msgid="861358534398115820">"ayer"</item>
-    <item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días."</item>
+    <item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
   </plurals>
   <plurals name="in_num_seconds">
     <item quantity="one" msgid="2729745560954905102">"en 1 segundo"</item>
@@ -1176,7 +1174,7 @@
     <item quantity="other" msgid="851164968597150710">"Hace <xliff:g id="COUNT">%d</xliff:g> minutos."</item>
   </plurals>
   <plurals name="abbrev_num_hours_ago">
-    <item quantity="one" msgid="4796212039724722116">"Hace 1 hora."</item>
+    <item quantity="one" msgid="4796212039724722116">"Hace 1 hora"</item>
     <item quantity="other" msgid="6889970745748538901">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
   <plurals name="abbrev_num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Iniciando Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamiento"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando la aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicaciones"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalizando el inicio"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se pudo conectar a la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una mala conexión a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"¿Permitir la conexión?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s quiere conectarse a %2$s."</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Una aplicación"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar Wi-Fi Direct. Se desactivará el funcionamiento de la zona o del cliente Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"La solicitud SS cambió por una solicitud DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"La solicitud SS cambió por una solicitud USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"La solicitud SS cambió por una nueva solicitud SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 96856c0..d56a893 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Hace 1 hora"</item>
     <item quantity="other" msgid="2467273239587587569">"Hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Últimos <xliff:g id="COUNT">%d</xliff:g> días"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"El mes pasado"</string>
     <string name="older" msgid="5211975022815554840">"Anterior"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android se está iniciando…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamiento."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>..."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicaciones"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalizando inicio..."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se ha podido establecer conexión con la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una conexión inestable a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"¿Permitir la conexión?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s quiere conectarse a %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Una aplicación"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar Wi-Fi Direct. Se desactivará el funcionamiento de la zona o del cliente Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"La solicitud SS se ha modificado para la solicitud DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"La solicitud SS se ha modificado para la solicitud USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"La solicitud SS se ha modificado para la nueva solicitud SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index ccb7b9f..eec356a 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 tund tagasi"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> tundi tagasi"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Viimased <xliff:g id="COUNT">%d</xliff:g> päeva"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Eelmisel kuul"</string>
     <string name="older" msgid="5211975022815554840">"Vanem"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android käivitub ..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Salvestusruumi optimeerimine."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. rakenduse <xliff:g id="NUMBER_1">%2$d</xliff:g>-st optimeerimine."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> ettevalmistamine."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Rakenduste käivitamine."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Käivitamise lõpuleviimine."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> töötab"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ei saanud WiFi-ga ühendust"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" on halb Interneti-ühendus."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Kas lubada ühendus?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s soovib luua ühenduse võrguga %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Rakendus %1$s soovib luua ühenduse WiFi-võrguga %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Rakendus"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WiFi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käivitage WiFi otseühendus. See lülitab välja WiFi kliendi/leviala."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-päring muudeti DIAL-päringuks."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-päring muudeti USSD-päringuks."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-päring muudeti uueks SS-päringuks."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Väline USB-port"</string>
 </resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 51e9fee..bf2b274 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -424,7 +424,7 @@
     <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"Lotu ahots bidezko elkarrekintzako zerbitzuei"</string>
     <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ahots bidezko elkarrekintzako zerbitzu baten goi-mailako interfazeari lotzea baimentzen die titularrei. Aplikazio normalek ez lukete beharko."</string>
     <string name="permlab_manageVoiceKeyphrases" msgid="1252285102392793548">"kudeatu ahozko gako-esaldiak"</string>
-    <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Ahoz esandako gako-hitzak hautemateko gako-esaldiak kudeatzea baimentzen die aplikazioei. Aplikazio normalek ez lukete behar."</string>
+    <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"Ahozko pasahitzak hautemateko gako-esaldiak kudeatzea baimentzen die aplikazioei. Aplikazio normalek ez lukete behar."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Lotu urruneko pantaila batera"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Urruneko pantaila baten goi-mailako interfazera lotzeko aukera ematen dio titularrari. Aplikazio normalek ez dute baimen hau behar."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"lotu widget-zerbitzu batekin"</string>
@@ -559,7 +559,7 @@
     <string name="permdesc_controlVpn" msgid="762852603315861214">"Sare pribatu birtualen behe-mailako eginbideak kontrolatzea baimentzen die aplikazioei."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Grabatu audio-irteera"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Audio-irteera grabatzeko eta birbideratzeko aukera ematen die aplikazioei."</string>
-    <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hauteman Hotword"</string>
+    <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hauteman ahozko pasahitza"</string>
     <string name="permdesc_captureAudioHotword" msgid="9151807958153056810">"Hotword bidez hauteman daitekeen audioa grabatzeko aukera ematen die aplikazioei. Atzeko planoan grabatzeak ez du bestelako audio-grabazioak (adibidez, bideokamera bidezkoak) egitea eragozten."</string>
     <string name="permlab_modifyAudioRouting" msgid="7738060354490807723">"Audio-bideratzea"</string>
     <string name="permdesc_modifyAudioRouting" msgid="7205731074267199735">"Audio-bideratzea zuzenean kontrolatzea eta audio-gidalerroei gainjartzea baimentzen die aplikazioei."</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Duela ordubete"</item>
     <item quantity="other" msgid="2467273239587587569">"duela <xliff:g id="COUNT">%d</xliff:g> ordu"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"azken <xliff:g id="COUNT">%d</xliff:g> egunak"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Azken hilabetea"</string>
     <string name="older" msgid="5211975022815554840">"Zaharragoa"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android abiarazten ari da…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Memoria optimizatzen."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikazio optimizatzen."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> prestatzen."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Aplikazioak abiarazten."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Bertsio-berritzea amaitzen."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> exekutatzen"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ezin izan da Wi-Fi sarera konektatu"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" Interneteko konexio txarra du."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Konektatzea baimendu nahi diozu?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s aplikazioak %2$s sarera konektatu nahi du"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s aplikazioak %2$s Wi-Fi sarera konektatu nahi du"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikazio bat"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Hasi Wi-Fi Direct. Wi-Fi bezeroa edo sare publikoa desaktibatuko da."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS eskaera DIAL eskaerara aldatu da."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS eskaera USSD eskaerara aldatu da."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS eskaera SS eskaera berrira aldatu da."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB ataka periferikoa"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b04d53c..7a71ceb 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"۱ ساعت قبل"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ساعت قبل"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> روز گذشته"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"ماه گذشته"</string>
     <string name="older" msgid="5211975022815554840">"قدیمی تر"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"‏Android در حال راه‌اندازی است..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"بهینه‌سازی فضای ذخیره‌سازی."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"در حال بهینه‌سازی برنامهٔ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"در حال آغاز برنامه‌ها."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"در حال اتمام راه‌اندازی."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> در حال اجرا"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏اتصال به Wi-Fi ممکن نیست"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" اتصال اینترنتی ضعیفی دارد."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"اتصال اجازه داده شود؟"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"‏%1$s می‌خواهد به %2$s متصل شود"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"برنامه"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"‏Wi-Fi Direct را شروع کنید. این کار نقطه اتصال/سرویس گیرنده Wi-Fi را غیرفعال خواهد کرد."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"‏درخواست SS به درخواست DIAL اصلاح می‌شود."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"‏درخواست SS به درخواست USSD اصلاح می‌شود."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"‏درخواست SS به درخواست SS جدید اصلاح می‌شود."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 49dd96f..feb93d9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 tunti sitten"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> tuntia sitten"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Viimeisen <xliff:g id="COUNT">%d</xliff:g> päivän aikana"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Viime kuussa"</string>
     <string name="older" msgid="5211975022815554840">"Vanhemmat"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android käynnistyy…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimoidaan tallennustilaa."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimoidaan sovellusta <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Valmistellaan: <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Käynnistetään sovelluksia."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Viimeistellään päivitystä."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> käynnissä"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-yhteyden muodostaminen epäonnistui"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" : huono internetyhteys."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Sallitaanko yhteys?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s haluaa yhdistää kohteeseen %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Sovellus %1$s yrittää yhdistää Wi-Fi-verkkoon %2$s."</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Sovellus"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Suora Wi-Fi-yhteys"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käynnistä suora Wi-Fi-yhteys. Wi-Fi-asiakas/-hotspot poistetaan käytöstä."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-pyyntö muutettiin DIAL-pyynnöksi."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-pyyntö muutettiin USSD-pyynnöksi."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-pyyntö muutettiin uudeksi SS-pyynnöksi."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB-oheislaiteportti"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index df8d9c1..a71d616 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Il y a 1 heure"</item>
     <item quantity="other" msgid="2467273239587587569">"il y a <xliff:g id="COUNT">%d</xliff:g> heures"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Les <xliff:g id="COUNT">%d</xliff:g> derniers jours"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Le mois dernier"</string>
     <string name="older" msgid="5211975022815554840">"Précédent"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android en cours de démarrage..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimisation du stockage."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Lancement des applications…"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalisation de la mise à jour."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" dispose d\'une mauvaise connexion Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Autoriser la connexion?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s souhaite se connecter à %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Une application"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Lancer le Wi-Fi Direct. Cela désactive le fonctionnement du Wi-Fi client ou via un point d\'accès."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"La demande SS a été modifiée et est maintenant une demande DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"La demande SS a été modifiée et est maintenant une demande USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"La demande SS a été modifiée et est maintenant une nouvelle demande SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1945e78..83df48d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"il y a 1 heure"</item>
     <item quantity="other" msgid="2467273239587587569">"Il y a <xliff:g id="COUNT">%d</xliff:g> heures"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Les <xliff:g id="COUNT">%d</xliff:g> derniers jours"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Le mois dernier"</string>
     <string name="older" msgid="5211975022815554840">"Préc."</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Démarrage d\'Android en cours"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimisation du stockage en cours…"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Lancement des applications…"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Finalisation de la mise à jour."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" dispose d\'une mauvaise connexion Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Autoriser la connexion ?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s souhaite se connecter à %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Une application"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Lancer le Wi-Fi Direct. Cela désactive le fonctionnement du Wi-Fi client ou via un point d\'accès."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"La requête SS a été remplacée par une requête DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"La requête SS a été remplacée par une requête USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"La requête SS a été remplacée par une autre requête SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 78d223c..b6122b4 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Hai 1 hora"</item>
     <item quantity="other" msgid="2467273239587587569">"hai <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Últimos <xliff:g id="COUNT">%d</xliff:g> días"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"O mes pasado"</string>
     <string name="older" msgid="5211975022815554840">"Antes"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Estase iniciando Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamento."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicacións."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Está finalizando o arranque"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> está en execución"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Non se puido conectar coa rede Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ten unha conexión a Internet deficiente."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Queres permitir a conexión?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s quere conectarse a %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"A aplicación %1$s quere conectarse á rede wifi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Unha aplicación"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Inicia Wi-Fi Direct. Esta acción desactivará o cliente e a zona interactiva da wifi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"A solicitude SS transformouse nunha solicitude DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"A solicitude SS transformouse nunha solicitude USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"A solicitude SS transformouse nunha nova solicitude SS."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Porto periférico USB"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index d17a5cb..64f0ab8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -71,7 +71,7 @@
     <string name="ClirMmi" msgid="7784673673446833091">"आउटगोइंग कॉलर ID"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"कनेक्ट किया गया लाइन आईडी"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"कनेक्ट किया गया लाइन आईडी प्रतिबंध"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"कॉल अग्रेषण"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"कॉल आगे भेजना"</string>
     <string name="CwMmi" msgid="9129678056795016867">"कॉल प्रतीक्षा"</string>
     <string name="BaMmi" msgid="455193067926770581">"कॉल बाधित करना"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"पासवर्ड बदलें"</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 घंटे पहले"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> घंटे पहले"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"अंतिम <xliff:g id="COUNT">%d</xliff:g> दिन"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"पिछला माह"</string>
     <string name="older" msgid="5211975022815554840">"इससे पुराना"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android प्रारंभ हो रहा है…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"मेमोरी ऑप्‍टिमाइज़ हो रही है."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप्स  अनुकूलित हो रहा है."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तैयार हो रहा है."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ऐप्स  प्रारंभ होने वाले हैं"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"बूट समाप्‍त हो रहा है."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> चल रही है"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाई-फ़ाई  से कनेक्‍ट नहीं हो सका"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" के पास एक कमज़ोर इंटरनेट कनेक्‍शन है."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"कनेक्शन की अनुमति दें?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s, %2$s से कनेक्ट होना चाहता/चाहती है"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s ऐप्‍लिकेशन %2$s वाई-फ़ाई नेटवर्क से कनेक्‍ट करना चाहता है"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"ऐप्लिकेशन"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"वाई-फ़ाई डायरेक्ट"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाई-फ़ाई  डायरेक्ट प्रारंभ करें. इससे वाई-फ़ाई  क्‍लाइंट/हॉटस्पॉट कार्यवाही बंद हो जाएगी."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS अनुरोध को DIAL अनुरोध में बदल दिया गया है."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS अनुरोध को USSD अनुरोध में बदल दिया गया है."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS अनुरोध को नए SS अनुरोध में बदल दिया गया है."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB पेरिफ़ेरल पोर्ट"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 21c9938a..d6c9660 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Prije 1 sata"</item>
     <item quantity="other" msgid="2467273239587587569">"Prije <xliff:g id="COUNT">%d</xliff:g> h"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Posljednjih ovoliko dana: <xliff:g id="COUNT">%d</xliff:g>"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Prošli mjesec"</string>
     <string name="older" msgid="5211975022815554840">"Starije"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Pokretanje Androida..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimiziranje pohrane."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimiziranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Pokretanje aplikacija."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Završetak inicijalizacije."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Izvodi se <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ne može se spojiti na Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internetsku vezu."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Dopustiti povezivanje?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s traži povezivanje sa sljedećim: %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikacija"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Izravni Wi-Fi"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Pokreni izravan rad s Wi-Fi mrežom. To će isključiti rad s Wi-Fi klijentom/žarišnom točkom."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS zahtjev izmijenjen je u DIAL zahtjev."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS zahtjev izmijenjen je u USSD zahtjev."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS zahtjev izmijenjen je u novi SS zahtjev."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 978d115..ec5e47e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -56,7 +56,7 @@
     <string name="badPin" msgid="9015277645546710014">"A megadott régi PIN kód helytelen."</string>
     <string name="badPuk" msgid="5487257647081132201">"A megadott PUK kód helytelen."</string>
     <string name="mismatchPin" msgid="609379054496863419">"A beírt PIN kódok nem egyeznek."</string>
-    <string name="invalidPin" msgid="3850018445187475377">"Írjon be egy 4-8 számjegyű PIN-kódot."</string>
+    <string name="invalidPin" msgid="3850018445187475377">"Írjon be egy 4-8 számjegyű PIN kódot."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"8 számjegyű vagy hosszabb PUK kódot írjon be."</string>
     <string name="needPuk" msgid="919668385956251611">"A SIM kártya le van zárva a PUK kóddal. A feloldáshoz adja meg a PUK kódot."</string>
     <string name="needPuk2" msgid="4526033371987193070">"A SIM kártya feloldásához adja meg a PUK2 kódot."</string>
@@ -75,7 +75,7 @@
     <string name="CwMmi" msgid="9129678056795016867">"Hívásvárakoztatás"</string>
     <string name="BaMmi" msgid="455193067926770581">"Hívásletiltás"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Jelszómódosítás"</string>
-    <string name="PinMmi" msgid="3113117780361190304">"PIN-kód módosítása"</string>
+    <string name="PinMmi" msgid="3113117780361190304">"PIN kód módosítása"</string>
     <string name="CnipMmi" msgid="3110534680557857162">"Szám hívása"</string>
     <string name="CnirMmi" msgid="3062102121430548731">"Hívószám korlátozva"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"Háromutas hívás"</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 órája"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> órája"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Elmúlt <xliff:g id="COUNT">%d</xliff:g> napban"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Múlt hónapban"</string>
     <string name="older" msgid="5211975022815554840">"Régebbi"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Az Android indítása…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Tárhely-optimalizálás."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Alkalmazás optimalizálása: <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> előkészítése."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Kezdő alkalmazások."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Rendszerindítás befejezése."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> fut"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nem sikerült csatlakozni a Wi-Fi hálózathoz"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" rossz internetkapcsolattal rendelkezik."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Engedélyezi a csatlakozást?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"A(z)%1$s szeretne csatlakozni a következőhöz: %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"A(z) %1$s alkalmazás szeretne csatlakozni a következő Wi-Fi hálózathoz: %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Egy alkalmazás"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct elindítása. A Wi-Fi kliens/hotspot ettől leáll."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Az SS-kérés módosítva DIAL-kérésre."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Az SS-kérés módosítva USSD-kérésre."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Az SS-kérés módosítva új SS-kérésre."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB-perifériaport"</string>
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 101a726..5e2c5a9 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -22,8 +22,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="byteShort" msgid="8340973892742019101">"Բ"</string>
     <string name="kilobyteShort" msgid="5973789783504771878">"Կբ"</string>
-    <string name="megabyteShort" msgid="6355851576770428922">"Մբ"</string>
-    <string name="gigabyteShort" msgid="3259882455212193214">"Գբ"</string>
+    <string name="megabyteShort" msgid="6355851576770428922">"ՄԲ"</string>
+    <string name="gigabyteShort" msgid="3259882455212193214">"ԳԲ"</string>
     <string name="terabyteShort" msgid="231613018159186962">"Տբ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Պբ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 ժամ առաջ"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ժամ առաջ"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Վերջին <xliff:g id="COUNT">%d</xliff:g> օրերին"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Անցյալ ամիս"</string>
     <string name="older" msgid="5211975022815554840">"Ավելի հին"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android-ը մեկնարկում է…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Պահեստի օպտիմալացում:"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Օպտիմալացվում է հավելված <xliff:g id="NUMBER_0">%1$d</xliff:g>-ը <xliff:g id="NUMBER_1">%2$d</xliff:g>-ից:"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը պատրաստվում է:"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Հավելվածները մեկնարկում են:"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Բեռնումն ավարտվում է:"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g>-ն աշխատում է"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Չհաջողվեց միանալ Wi-Fi-ին"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ունի թույլ ինտերնետ կապ:"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Թույլատրե՞լ կապը:"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s օգտվողը ցանկանում է կապվել %2$s-ին"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s հավելվածը ցանկանում է միանալ %2$s Wifi ցանցին"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Հավելված"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ուղիղ"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Մեկնարկել Wi-Fi ուղին: Այն կանջատի Wi-Fi հաճախորդ/թեժ կետ գործողությունը:"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS հարցումը փոխվել է DIAL հարցման:"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS հարցումը փոխվել է USSD հարցման:"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS հարցումը փոխվել է նոր SS հարցման:"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB արտաքին միացք"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 085939a..70bcb1b 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 jam yang lalu"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> hari terakhir"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Bulan lalu"</string>
     <string name="older" msgid="5211975022815554840">"Lawas"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Memulai Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Mengoptimalkan penyimpanan."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Mengoptimalkan aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Menyiapkan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Memulai aplikasi."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Menyelesaikan boot."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> berjalan"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak dapat tersambung ke Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" memiliki sambungan internet yang buruk."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Izinkan hubungan?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ingin terhubung ke %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Aplikasi %1$s ingin tersambung ke Jaringan Wifi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikasi"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Memulai Wi-Fi Direct. Opsi ini akan mematikan hotspot/klien Wi-Fi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Permintaan SS diubah menjadi permintaan DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Permintaan SS diubah menjadi permintaan USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Permintaan SS diubah menjadi permintaan SS baru."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Port Periferal USB"</string>
 </resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 2839911..1d7aaba 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"fyrir klukkustund"</item>
     <item quantity="other" msgid="2467273239587587569">"fyrir <xliff:g id="COUNT">%d</xliff:g> klukkustundum"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Síðustu <xliff:g id="COUNT">%d</xliff:g> daga"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Í síðasta mánuði"</string>
     <string name="older" msgid="5211975022815554840">"Eldra"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android er að ræsast…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Fínstillir geymslu."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Fínstillir forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Undirbýr <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ræsir forrit."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Lýkur ræsingu."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> er í gangi"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ekki var hægt að tengjast Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" er með lélegt netsamband."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Leyfa tengingu?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s vill fá að tengjast %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Forritið %1$s vill tengjast Wi-Fi netinu %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Forrit"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Ræsa Wi-Fi Direct. Þetta mun slökkva á Wi-Fi biðlara/aðgangsstað."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-beiðni er breytt í DIAL-beiðni."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-beiðni er breytt í USSD-beiðni."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-beiðni er breytt í nýja SS-beiðni."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB-tengi fyrir jaðartæki"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e1f1d7c..6443c1a 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 ora fa"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ore fa"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Ultimi <xliff:g id="COUNT">%d</xliff:g> giorni"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Ultimo mese"</string>
     <string name="older" msgid="5211975022815554840">"Precedente"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Avvio di Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ottimizzazione archiviazione."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ottimizzazione applicazione <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Avvio applicazioni."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Conclusione dell\'avvio."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> in esecuzione"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossibile connettersi alla rete Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ha una connessione Internet debole."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Consentire la connessione?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s vorrebbe connettersi a %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Un\'applicazione"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Avvia Wi-Fi Direct. Verrà disattivato il client/hotspot Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"La richiesta SS è stata modificata in richiesta DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"La richiesta SS è stata modificata in richiesta USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"La richiesta SS è stata modificata in nuova richiesta SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 196a774..3c5390a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"לפני שעה"</item>
     <item quantity="other" msgid="2467273239587587569">"לפני <xliff:g id="COUNT">%d</xliff:g> שעות"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> הימים האחרונים"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"בחודש שעבר"</string>
     <string name="older" msgid="5211975022815554840">"ישן יותר"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"‏הפעלת Android מתחילה…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"מתבצעת אופטימיזציה של האחסון."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"מבצע אופטימיזציה של אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"מפעיל אפליקציות."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"מסיים אתחול."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> פועל"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏אין אפשרות להתחבר ל-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" אינו מחובר היטב לאינטרנט."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"האם להתיר את החיבור?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"‏%1$s רוצה להתחבר אל %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"אפליקציה"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"‏Wi-Fi ישיר"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"‏הפעל Wi-Fi ישיר. פעולה זו תכבה את הנקודה לשיתוף אינטרנט ב-Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"‏בקשת SS שונתה לבקשת DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"‏בקשת SS שונתה לבקשת USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"‏בקשת SS שונתה לבקשת SS חדשה."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 67b72d4..3109a9b 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1時間前"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>時間前"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"過去<xliff:g id="COUNT">%d</xliff:g>日間"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"先月"</string>
     <string name="older" msgid="5211975022815554840">"もっと前"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Androidの起動中…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ストレージを最適化しています。"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>個中<xliff:g id="NUMBER_0">%1$d</xliff:g>個のアプリを最適化しています。"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"アプリを起動しています。"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ブートを終了しています。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g>を実行中"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiに接続できませんでした"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" はインターネット接続に問題があります。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"接続を許可しますか?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$sさんが「%2$s」への接続を希望しています"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"アプリ"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Directを開始します。これによりWi-Fiクライアント/アクセスポイントがOFFになります。"</string>
@@ -1418,7 +1419,7 @@
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"カメラとして接続"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"インストーラとして接続"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"USBアクセサリを接続しました"</string>
-    <string name="usb_notification_message" msgid="2290859399983720271">"他のUSBオプションをタップしてください。"</string>
+    <string name="usb_notification_message" msgid="2290859399983720271">"USB接続方法を変更するにはタップしてください。"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"USBストレージをフォーマットしますか?"</string>
     <string name="extmedia_format_title" product="default" msgid="3648415921526526069">"SDカードをフォーマットしますか?"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"USBストレージに保存されているファイルはすべて消去されます。この操作は元に戻せません。"</string>
@@ -1847,7 +1848,7 @@
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使用するその他のアプリは、起動しても更新されないことがあります。\n\nバッテリーセーバーは端末の充電中は自動的にOFFになります。"</string>
-    <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>にダウンロードが終わるまで"</string>
+    <string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>にダウンタイムが終わるまで"</string>
     <string name="downtime_condition_line_one" msgid="8762708714645352010">"ダウンタイム終了まで"</string>
   <plurals name="zen_mode_duration_minutes_summary">
     <item quantity="one" msgid="3177683545388923234">"1分間(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>まで)"</item>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SSリクエストはDIALリクエストに変更されました。"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SSリクエストはUSSDリクエストに変更されました。"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SSリクエストは新しいSSリクエストに変更されました。"</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 9ab84bef4..3c84acb 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 საათის წინ"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> საათის წინ"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"ბოლო <xliff:g id="COUNT">%d</xliff:g> დღე"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"გასული თვე"</string>
     <string name="older" msgid="5211975022815554840">"უფრო ძველი"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android იწყება…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"მეხსიერების ოპტიმიზირება."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"მიმდინარეობს აპლიკაციების ოპტიმიზაცია. დასრულებულია <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"ემზადება <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"აპების ჩართვა"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ჩატვირთვის დასასრული."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> გაშვებულია"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-თან დაკავშირება ვერ მოხერხდა"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" აქვს ცუდი ინტერნეტ კავშირი."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"გსურთ კავშირის დაშვება?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s-ს სურს %2$s-თან დაკავშირება"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"განაცხადს %1$s სურს დაუკავშირდეს Wifi ქსელს %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"აპლიკაცია"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ჩართეთ Wi-Fi Direct. ეს გამოიწვევს Wi-Fi კლიენტისა/უსადენო ქსელის გამორთვას."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS მოთხოვნა შეიცვალა DIAL მოთხოვნით."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS მოთხოვნა შეიცვალა USSD მოთხოვნით."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS მოთხოვნა შეიცვალა ახალი SS მოთხოვნით."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"პერიფერიული USB პორტი"</string>
 </resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 255fedc..f8df80c 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 сағат бұрын"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> сағат бұрын"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Соңғы <xliff:g id="COUNT">%d</xliff:g> күнде"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Соңғы ай"</string>
     <string name="older" msgid="5211975022815554840">"Ескілеу"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android іске қосылуда…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Қойманы оңтайландыру."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ішінен <xliff:g id="NUMBER_0">%1$d</xliff:g> қолданба оңтайландырылуда."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> дайындалуда."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Қолданбалар іске қосылуда."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Қосуды аяқтауда."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> қосылған"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi желісіне қосыла алмады"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" Интернет байланысы нашар."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Қосылуға рұқсат ету керек пе?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s %2$s қосылғысы келеді"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s қолданбасы %2$s Wi-Fi желісіне қосылғысы келеді"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Қолданба"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi тікелей"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Тікелей байланысын бастау. Бұл Wi-Fi клиент/хот-спотты өшіреді."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS сұрауы DIAL сұрауына өзгертілді."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS сұрауы USSD сұрауына өзгертілді."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS сұрауы жаңа SS сұрауына өзгертілді."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB перифериялық порты"</string>
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index f8e88f5..2e973dc 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"១ ម៉ោង​មុន"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ម៉ោង​មុន"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> ថ្ងៃ​ចុងក្រោយ"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"ខែ​មុន"</string>
     <string name="older" msgid="5211975022815554840">"ចាស់​ជាង"</string>
   <plurals name="num_days_ago">
@@ -1305,6 +1303,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android កំពុង​ចាប់ផ្ដើម…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"កំពុងធ្វើឲ្យឧបករណ៍ផ្ទុកមានប្រសិទ្ធភាព។"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"ធ្វើ​ឲ្យ​កម្មវិធី​ប្រសើរ​ឡើង <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g> ។"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"កំពុងរៀបចំ <xliff:g id="APPNAME">%1$s</xliff:g>។"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ចាប់ផ្ដើម​កម្មវិធី។"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"បញ្ចប់​ការ​ចាប់ផ្ដើម។"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
@@ -1350,7 +1349,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"មិន​​អាច​តភ្ជាប់​វ៉ាយហ្វាយ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" មាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត​មិន​ល្អ។"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"អនុញ្ញាត​ភ្ជាប់?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ចង់​ភ្ជាប់​ %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"កម្មវិធី %1$s ចង់ភ្ជាប់ទៅបណ្តាញ Wifi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"កម្មវិធី"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"វ៉ាយហ្វាយ​ផ្ទាល់"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ចាប់ផ្ដើម​វ៉ាយហ្វាយ​ផ្ទាល់។ វា​នឹង​បិទ​វ៉ាយហ្វាយ​ហតស្ពត។"</string>
@@ -1881,4 +1880,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"សំណើរ SS ត្រូវបានកែសម្រួលទៅតាមសំណើរការហៅទូរស័ព្ទ។"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"សំណើរ SS ត្រូវបានកែសម្រួលទៅតាមសំណើរ USSD។"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"សំណើរ SS ត្រូវបានកែសម្រួលទៅតាមសំណើរ SS ថ្មី។"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"ឧបករណ៍រន្ធ USB បន្ថែម"</string>
 </resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 0d18fce..befcfd2 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 ಗಂಟೆ ಹಿಂದೆ"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳ ಹಿಂದೆ"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"ಕಳೆದ <xliff:g id="COUNT">%d</xliff:g> ದಿನಗಳಲ್ಲಿ"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"ಕಳೆದ ತಿಂಗಳು"</string>
     <string name="older" msgid="5211975022815554840">"ಹಳೆಯದು"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ಸಂಗ್ರಹಣೆಯನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ಬೂಟ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ಕಳಪೆ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿದೆ."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ಸಂಪರ್ಕವನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ಅವರು %2$s ಗೆ ಸಂಪರ್ಕಿಸಲು ಬಯಸುತ್ತಾರೆ"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%2$s ವೈಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು %1$s ಅಪ್ಲಿಕೇಶನ್‌ ಬಯಸುತ್ತದೆ"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"ಅಪ್ಲಿಕೇಶನ್"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ಡೈರೆಕ್ಟ್"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi ಡೈರೆಕ್ಟ್ ಪ್ರಾರಂಭಿಸಿ. ಇದು Wi-Fi ಕ್ಲೈಂಟ್‌/ಹಾಟ್‌ಸ್ಪಾಟ್ ಅನ್ನು ಆಫ್ ಮಾಡುತ್ತದೆ."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS ವಿನಂತಿಯನ್ನು DIAL ವಿನಂತಿಗೆ ಮಾರ್ಪಡಿಸಲಾಗಿದೆ."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS ವಿನಂತಿಯನ್ನು USSD ವಿನಂತಿಗೆ ಮಾರ್ಪಡಿಸಲಾಗಿದೆ."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS ವಿನಂತಿಯನ್ನು ಹೊಸ SS ವಿನಂತಿಗೆ ಮಾರ್ಪಡಿಸಲಾಗಿದೆ."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB ಹೊರಭಾಗದ ಪೋರ್ಟ್"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index c52c351..7594e18 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1시간 전"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>시간 전"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"지난 <xliff:g id="COUNT">%d</xliff:g>일"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"지난 달"</string>
     <string name="older" msgid="5211975022815554840">"이전"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android가 시작되는 중…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"저장소 최적화 중"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>개 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>개 최적화 중"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"앱을 시작하는 중입니다."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"부팅 완료"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> 실행 중"</string>
@@ -1348,8 +1348,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi에 연결할 수 없습니다"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 인터넷 연결 상태가 좋지 않습니다."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"연결을 허용하시겠습니까?"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for wifi_connect_alert_message (8930084523889618078) -->
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
     <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"앱"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
@@ -1881,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS 요청이 DIAL 요청으로 수정됩니다."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS 요청이 USSD 요청으로 수정됩니다."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS 요청이 새로운 SS 요청으로 수정됩니다."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 2b45690..9675fdc 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1479,6 +1479,7 @@
     <!-- no translation found for num_minutes_ago:other (2176942008915455116) -->
     <!-- no translation found for num_hours_ago:one (9150797944610821849) -->
     <!-- no translation found for num_hours_ago:other (2467273239587587569) -->
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <!-- no translation found for last_num_days:other (3069992808164318268) -->
     <!-- no translation found for last_month (3959346739979055432) -->
     <skip />
@@ -1661,6 +1662,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android жүргүзүлүүдө…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Сактагыч ыңгайлаштырылууда."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо ыңгайлаштырылууда."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Колдонмолорду иштетип баштоо"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Жүктөө аякталууда."</string>
     <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
@@ -1717,7 +1719,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi менен туташуу түзүлбөдү"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" хотспотунун интернет байланышы начар."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Туташууга уруксатпы?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s %2$s менен туташкысы келди"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s колдонмосу %2$s Wifi тармагына туташкысы келет"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Колдонмо"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Дайректи иштетүү. Бул Wi-Fi клиентти/хотспотту өчүрөт."</string>
@@ -2357,4 +2359,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS сурамы DIAL сурамына өзгөртүлдү."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS сурамы USSD сурамына өзгөртүлдү."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS сурамы жаңы SS сурамына өзгөртүлдү."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB Сырткы оюкча"</string>
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index ed47bbb..21644ec 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 ຊົ່ວໂມງກ່ອນໜ້ານີ້"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງທີ່ຜ່ານມາ"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> ມື້ທີ່ຜ່ານມາ"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"ເດືອນແລ້ວ"</string>
     <string name="older" msgid="5211975022815554840">"ເກົ່າກວ່າ"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"ກຳ​ລັງ​ເລີ່ມລະ​ບົບ​ Android …"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ການ​ປັບ​ບ່ອນ​ເກັບ​ຂໍ້​ມູນ​ໃຫ້​ເໝາະ​ສົມ."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"ກຳລັງ​ປັບປຸງ​ປະສິດທິພາບ​ແອັບຯ​ທີ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຈາກ​ທັງ​ໝົດ <xliff:g id="NUMBER_1">%2$d</xliff:g> ແອັບຯ."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"ກຳ​ລັງ​ກຽມ <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ກຳລັງເປີດແອັບຯ."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ກຳລັງສຳເລັດການເປີດລະບົບ."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງເຮັດວຽກ"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ບໍ່ສາມາດເຊື່ອມຕໍ່ Wi-Fi ໄດ້"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ມີສັນຍານອິນເຕີເນັດທີ່ບໍ່ດີ."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"​ອະ​ນຸ​ຍາດ​ການ​ເຊື່ອມ​ຕໍ່ຫຼື​ບໍ່?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ​ຕ້ອງ​ການ​ທີ່​ຈະ​ເຊື່ອມ​ຕໍ່​ຫາ %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"ແອັບ​ພ​ລິ​ເຄ​ຊັນ %1$s ຢາກ​ຈະ​ເຊື່ອມ​ຕໍ່​ກັບ​ເຄືອ​ຂ່າຍ Wifi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"​ແອັບ​ພລິ​ເຄ​ຊັນ"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ເລີ່ມ Wi-Fi Direct. ນີ້ຈະເປັນການປິດ Wi-Fi client/hotspot."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"ການ​ຂໍ SS ຖືກ​ດັດ​ແປງ​ເປັນ​ການ​ຂໍ DIAL ແລ້ວ."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"ການ​ຂໍ SS ຖືກ​ດັດ​ແປງ​ເປັນ​ການ​ຂໍ USSD ແລ້ວ."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"ການ​ຂໍ SS ຖືກ​ດັດ​ແປງ​ເປັນ​ການ​ຂໍ SS ໃໝ່​ແລ້ວ."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"ຊ່ອງ​ຮອບນອກ USB"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f22ddea..9e5bcb5 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Prieš 1 valandą"</item>
     <item quantity="other" msgid="2467273239587587569">"Prieš <xliff:g id="COUNT">%d</xliff:g> val."</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Paskutinės <xliff:g id="COUNT">%d</xliff:g> dienos (-ų)"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Paskutinį mėnesį"</string>
     <string name="older" msgid="5211975022815554840">"Senesni"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Paleidžiama „Android“…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizuojama saugykla."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizuojama <xliff:g id="NUMBER_0">%1$d</xliff:g> progr. iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Paleidžiamos programos."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Užbaigiamas paleidimas."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Vykdoma „<xliff:g id="APP">%1$s</xliff:g>“"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepavyko prisijungti prie „Wi-Fi“"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" turi prastą interneto ryšį."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Leisti prisijungti?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"„%1$s“ nori prisijungti prie „%2$s“"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Programa"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Tiesioginis „Wi-Fi“ ryšys"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Paleiskite „Wi-Fi Direct“. Bus išjungta „Wi-Fi“ programa / viešosios interneto prieigos taškas."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS užklausa pakeista į DIAL užklausą."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS užklausa pakeista į USSD užklausą."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS užklausa pakeista į naują SS užklausą."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1c1f0c5..20bad77 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Pirms 1 stundas"</item>
     <item quantity="other" msgid="2467273239587587569">"Pirms <xliff:g id="COUNT">%d</xliff:g> stundas(-ām)"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Pēdējās <xliff:g id="COUNT">%d</xliff:g> dienās"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Iepriekšējā mēnesī"</string>
     <string name="older" msgid="5211975022815554840">"Vecāks"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Notiek Android palaišana…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Notiek krātuves optimizēšana."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Tiek optimizēta <xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Notiek lietotņu palaišana."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Tiek pabeigta sāknēšana."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> darbojas"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nevarēja izveidot savienojumu ar Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ir slikts interneta savienojums."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vai atļaut savienojumu?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s vēlas izveidot savienojumu ar tīklu %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Lietojumprogramma"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Palaist programmu Wi-Fi Direct. Tādējādi tiks izslēgta Wi-Fi klienta/tīklāja darbība."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS pieprasījums ir mainīts uz DIAL pieprasījumu."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS pieprasījums ir mainīts uz USSD pieprasījumu."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS pieprasījums ir mainīts uz jaunu SS pieprasījumu."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index df4b13b..72dd8e2 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Пред 1 час"</item>
     <item quantity="other" msgid="2467273239587587569">"пред <xliff:g id="COUNT">%d</xliff:g> часа"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Последните <xliff:g id="COUNT">%d</xliff:g> дена"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Минатиот месец"</string>
     <string name="older" msgid="5211975022815554840">"Постари"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android стартува…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимизирање на складирањето."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Се оптимизира апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Се подготвува <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Се стартуваат апликациите."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Подигањето завршува."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> работи"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можеше да се поврзе со Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има слаба конекција на интернет."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Дозволете поврзување?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s сака да се поврзе на %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Апликацијата %1$s сака да се поврзе со Wifi-мрежата %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Апликација"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Започни Wi-Fi Direct. Ова ќе го исклучи Wi-Fi клиентот/хточката на пристап."</string>
@@ -1881,4 +1880,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Барањето SS е изменето во барање DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Барањето SS е изменето во барање USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Барањето SS е изменето во ново барање SS."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Надворешна порта на УСБ"</string>
 </resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index b9bfa99..134a9b5 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 മണിക്കൂര്‍ മുമ്പ്"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> മണിക്കൂർ മുമ്പ്"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"കഴിഞ്ഞ <xliff:g id="COUNT">%d</xliff:g> ദിവസം"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"കഴിഞ്ഞ മാസം"</string>
     <string name="older" msgid="5211975022815554840">"പഴയത്"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android ആരംഭിക്കുന്നു…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"സംഭരണം ഒപ്‌റ്റിമൈസ് ചെയ്യുന്നു."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> അപ്ലിക്കേഷൻ ഓപ്റ്റിമൈസ് ചെയ്യുന്നു."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> തയ്യാറാക്കുന്നു."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"അപ്ലിക്കേഷനുകൾ ആരംഭിക്കുന്നു."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ബൂട്ട് ചെയ്യൽ പൂർത്തിയാകുന്നു."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> പ്രവർത്തിക്കുന്നു"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-ലേക്ക് കണക്‌റ്റുചെയ്യാൻ കഴിഞ്ഞില്ല"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" മോശം ഇന്റർനെറ്റ് കണക്ഷനാണുള്ളത്."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"കണക്ഷൻ അനുവദിക്കണോ?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s, %2$s എന്നതിലേക്ക് കണക്‌റ്റുചെയ്യാൻ ആഗ്രഹിക്കുന്നു"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"അപ്ലിക്കേഷൻ %1$s Wifi നെറ്റ്‌വർക്കിലേക്ക് കണക്‌റ്റുചെയ്യാൻ താൽപ്പര്യപ്പെടുന്നു %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"ഒരു അപ്ലിക്കേഷൻ"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ഡയറക്‌ട്"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi ഡയറക്റ്റ് ആരംഭിക്കുക. ഇത് Wi-Fi ക്ലയന്റ്/ഹോട്ട്‌സ്‌പോട്ട് ഓഫാക്കും."</string>
@@ -1877,4 +1876,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS അഭ്യർത്ഥന, DIAL അഭ്യർത്ഥനയായി പരിഷ്‌ക്കരിച്ചു."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS അഭ്യർത്ഥന, USSD അഭ്യർത്ഥനയായി പരിഷ്‌ക്കരിച്ചു."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS അഭ്യർത്ഥന, പുതിയ SS അഭ്യർത്ഥനയായി പരിഷ്‌ക്കരിച്ചു."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB പെരിഫറൽ പോർട്ട്"</string>
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index a14588d..da08b72 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 цагийн өмнө"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> цагийн өмнө"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Сүүлийн <xliff:g id="COUNT">%d</xliff:g> өдөр"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Сүүлийн сар"</string>
     <string name="older" msgid="5211975022815554840">"Хуучин"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Андройд эхэлж байна..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Хадгалалтыг сайжруулж байна."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>-н <xliff:g id="NUMBER_0">%1$d</xliff:g> апп-г тохируулж байна."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Бэлдэж байна <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Апп-г эхлүүлж байна."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Эхлэлийг дуусгаж байна."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ажиллаж байна"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-д холбогдож чадсангүй"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" Интернет холболт муу байна."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Холболтыг зөвшөөрөх үү?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s %2$s-тай холбогдохыг хүсэж байна"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Програм %1$s нь Wifi сүлжээ %2$s-тай холбох хүсэлтэй байна"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Аппликешн"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Шууд"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Шуудыг эхлүүлнэ үү. Энэ нь Wi-Fi клиент/холболтын цэг унтраана."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS хүсэлтийг DIAL хүсэлт болгон өөрчилсөн байна"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS хүсэлтийг USSD хүсэлт болгон өөрчилсөн байна."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS хүсэлтийг шинэ SS хүсэлт болгон өөрчилсөн байна."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB Peripheral Port"</string>
 </resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 55daa3a..a2c21bd 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -218,7 +218,7 @@
     <string name="permgroupdesc_location" msgid="5704679763124170100">"आपल्या प्रत्यक्ष स्थानाचे परीक्षण करेल."</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"नेटवर्क संप्रेषण"</string>
     <string name="permgroupdesc_network" msgid="4478299413241861987">"विविध नेटवर्क वैशिष्ट्यांवर प्रवेश करेल."</string>
-    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"ब"</string>
+    <string name="permgrouplab_bluetoothNetwork" msgid="1585403544162128109">"ब्लूटुथ"</string>
     <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"ब द्वारे डिव्हाइसेसवर आणि नेटवर्कवर प्रवेश करेल."</string>
     <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"ऑडिओ सेटिंग्ज"</string>
     <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"ऑडिओ सेटिंग्ज बदला."</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 तासापूर्वी"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> तासांपूर्वी"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"अंतिम <xliff:g id="COUNT">%d</xliff:g> दिवस"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"अंतिम महिना"</string>
     <string name="older" msgid="5211975022815554840">"अधिक जुने"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android प्रारंभ करत आहे…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"संचयन ऑप्टिमाइझ करत आहे."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अॅप ऑप्टिमाइझ करत आहे."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करीत आहे."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"अॅप्स प्रारंभ करत आहे."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"बूट समाप्त होत आहे."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> चालत आहे"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाय-फाय ला कनेक्ट करू शकलो नाही"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" खराब इंटरनेट कनेक्शन आहे."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"कनेक्शनला अनुमती द्यायची?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s %2$s शी कनेक्ट करू इच्छितात"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s अनुप्रयोग %2$s वायफाय नेटवर्कशी कनेक्ट करू इच्छित आहे"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"अनुप्रयोग"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"वाय-फाय थेट"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाय-फाय थेट प्रारंभ करा. हे वाय-फाय क्लायंट/हॉटस्पॉट बंद करेल."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS विनंती डायल विनंतीवर सुधारित केली आहे."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS विनंती USSD विनंतीवर सुधारित केली आहे."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS विनंती नवीन SS विनंतीवर सुधारित केली आहे."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB बाह्यवर्ती पोर्ट"</string>
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 7ec40c4..3ca56d7 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 jam yang lalu"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> hari terakhir"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Bulan lepas"</string>
     <string name="older" msgid="5211975022815554840">"Lebih lama"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android sedang dimulakan…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Mengoptimumkan storan."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Mengoptimumkan apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Menyediakan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Memulakan apl."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"But akhir."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> dijalankan"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak boleh menyambung kepada Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" mempunyai sambungan internet yang kurang baik."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Benarkan sambungan?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ingin menyambung ke %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Aplikasi %1$s ingin menyambung ke Rangkaian Wifi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Satu aplikasi"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Langsung"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Mulakan Wi-Fi Langsung. Hal ini akan mematikan pengendalian klien/liputan Wi-Fi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Permintaan SS diubah kepada permintaan DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Permintaan SS diubah kepada permintaan USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Permintaan SS diubah kepada permintaan SS baharu."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Port Persisian USB"</string>
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 6e0b5ad..c8fb23c 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"လွနခဲ့သော ၁နာရီက"</item>
     <item quantity="other" msgid="2467273239587587569">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> နာရီက"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"ပြီးခဲ့သော<xliff:g id="COUNT">%d</xliff:g>ရက်က"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"ပြီးခဲ့သောလ"</string>
     <string name="older" msgid="5211975022815554840">"ယခင်က"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android စတင်နေ…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"သိုလှောင်မှုအား ပြုပြင်ခြင်း။"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> ထဲက app<xliff:g id="NUMBER_1">%2$d</xliff:g>ကို ဆီလျော်အောင် လုပ်နေ"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> အားပြင်ဆင်နေသည်။"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"appများကို စတင်နေ"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"လုပ်ငန်းစနစ်ထည့်သွင်း၍ ပြန်လည်စတင်ရန် ပြီးပါပြီ"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> က အလုပ်လုပ်နေသည်"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ဝိုင်ဖိုင်ကိုချိတ်ဆက်မရပါ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" အင်တာနက် ဆက်သွယ်မှု ကောင်းကောင်းမရှိပါ"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ချိတ်ဆက်မှုကို ခွင့်ပြုမလား?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s က %2$s သို့ ချိတ်ဆက်ချင်"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"အပ္ပလီကေးရှင်း %1$s သည် ဝိုင်ဖိုင်ကွန်ရက် %2$s ကိုချိတ်ဆက်လိုသည်"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"အပလီကေးရှင်း"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"တိုက်ရိုက် ဝိုင်ဖိုင်"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"တိုက်ရိုက်ဝိုင်ဖိုင်ကို စတင်ပါ။ ၎င်းသည် ဝိုင်ဖိုင် ဟော့စပေါ့ကို ရပ်ဆိုင်းစေမှာ ဖြစ်ပါသည်။"</string>
@@ -1877,4 +1876,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"DIAL တောင်းဆိုချက်အရ SS တောင်းဆိုချက်အား ပြင်ဆင်ထား၏။"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"USSD တောင်းဆိုချက်အရ SS တောင်းဆိုချက်အား ပြင်ဆင်ထား၏။"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS တောင်းဆိုချက်အရ SS တောင်းဆိုချက်အား ပြင်ဆင်ထား၏။"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"အန်းဒရွိုက်"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB ဘေးရှိပို့တ်"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index dc38563..856e2d3 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"for en time siden"</item>
     <item quantity="other" msgid="2467273239587587569">"for <xliff:g id="COUNT">%d</xliff:g> timer siden"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Siste <xliff:g id="COUNT">%d</xliff:g> dager"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Forrige måned"</string>
     <string name="older" msgid="5211975022815554840">"Eldre"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android starter …"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimaliser lagring."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimaliserer app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starter apper."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Ferdigstiller oppstart."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> kjører"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan ikke koble til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig Internett-tilkobling."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vil du tillat tilkoblingen?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s prøver å koble til %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Appen %1$s vil koble til Wi-Fi-nettverket %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"En app"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. Dette deaktiverer Wi-Fi-klienten/-sonen."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-forespørselen er endret til en RINGE-forespørsel."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-forespørselen er endret til en USSD-forespørsel."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-forespørselen er endret til en ny SS-forespørsel."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Port for USB-tilleggsutstyr"</string>
 </resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index fb8e1c2..73aa852 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"१ घन्टा अघि"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> घन्टा अघि"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"अन्तिम <xliff:g id="COUNT">%d</xliff:g> दिन"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"अन्तिम महिना"</string>
     <string name="older" msgid="5211975022815554840">"पुरानो"</string>
   <plurals name="num_days_ago">
@@ -1309,6 +1307,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android शुरू हुँदैछ..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"भण्डारण अनुकूलन गर्दै।"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"अनुप्रयोग अनुकुल हुँदै <xliff:g id="NUMBER_0">%1$d</xliff:g> को <xliff:g id="NUMBER_1">%2$d</xliff:g>।"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तयारी गर्दै।"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"सुरुवात अनुप्रयोगहरू।"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"बुट पुरा हुँदै।"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> चलिरहेको छ"</string>
@@ -1354,7 +1353,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाइ-फाइसँग जडान गर्न सकेन"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" कमजोर इन्टरनेट जडान छ।"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"जडान अनुमति दिने हो?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ले %2$s मा जडान गर्न चाहन्छ"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"अनुप्रयोग %1$s वाइफाइ नेटवर्क %2$s मा जडान गर्न चाहन्छ"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"एउटा अनुप्रयोग"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"वाइफाइ प्रत्यक्ष"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाइफाइ सिधा सुरु गर्नुहोस्। यसले वाइफाइ ग्राहक/हट्स्पटलाई बन्द गराउने छ।"</string>
@@ -1885,4 +1884,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS अनुरोध  DIAL अनुरोधमा परिमार्जन गरिएको छ।"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS अनुरोध USSD अनुरोधमा परिमार्जन गरिएको छ।"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS अनुरोध नयाँ SS अनुरोधमा परिमार्जन गरिएको छ।"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB परिधीय पोर्ट"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 75f4a74..fc496aa 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 uur geleden"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> uur geleden"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Afgelopen <xliff:g id="COUNT">%d</xliff:g> dagen"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Afgelopen maand"</string>
     <string name="older" msgid="5211975022815554840">"Ouder"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android wordt gestart…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Opslagruimte wordt geoptimaliseerd."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g> optimaliseren."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> voorbereiden."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Apps starten."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Opstarten afronden."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> wordt uitgevoerd"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan geen verbinding maken met wifi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" heeft een slechte internetverbinding."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Verbinding toestaan?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s wilt verbinding maken met %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"App %1$s wil verbinding maken met wifi-netwerk %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Een app"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wifi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wifi Direct starten. Hierdoor wordt de wifi-client/hotspot uitgeschakeld."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-verzoek is gewijzigd in DIAL-verzoek."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-verzoek is gewijzigd in USSD-verzoek."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-verzoek is gewijzigd in nieuw SS-verzoek."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Poort voor USB-randapparatuur"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 2482b0a..06cca3b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -269,13 +269,13 @@
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Dostęp do karty SD."</string>
     <string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"Funkcje ułatwień dostępu"</string>
     <string name="permgroupdesc_accessibilityFeatures" msgid="4205196881678144335">"Funkcje, których może zażądać technologia ułatwień dostępu."</string>
-    <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pobierz zawartość okna"</string>
+    <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pobieranie zawartości okna"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Sprawdzanie zawartości okna, z którego korzystasz."</string>
-    <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Włącz czytanie dotykiem"</string>
+    <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Włączenie czytania dotykiem"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"Klikane elementy będą wymawiane na głos, a ekran można przeglądać, używając gestów."</string>
-    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Włącz ułatwienia dostępu w internecie"</string>
+    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Włączenie ułatwień dostępu w internecie"</string>
     <string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Można zainstalować skrypty, by zawartość aplikacji była łatwiej dostępna."</string>
-    <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Obserwuj wpisywany tekst"</string>
+    <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Obserwowanie wpisywanego tekstu"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Obejmuje informacje osobiste, takie jak numery kart kredytowych i hasła."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"wyłączanie lub zmienianie paska stanu"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"godzinę temu"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> godz. temu"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Ostatnie (<xliff:g id="COUNT">%d</xliff:g>) dni"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Ostatni miesiąc"</string>
     <string name="older" msgid="5211975022815554840">"Starsze"</string>
   <plurals name="num_days_ago">
@@ -1200,7 +1198,7 @@
     <item quantity="other" msgid="2973062968038355991">"za <xliff:g id="COUNT">%d</xliff:g> dni"</item>
   </plurals>
     <string name="preposition_for_date" msgid="9093949757757445117">"w dniu <xliff:g id="DATE">%s</xliff:g>"</string>
-    <string name="preposition_for_time" msgid="5506831244263083793">"o godzinie <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="preposition_for_time" msgid="5506831244263083793">"o godzinie <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="preposition_for_year" msgid="5040395640711867177">"w <xliff:g id="YEAR">%s</xliff:g> r."</string>
     <string name="day" msgid="8144195776058119424">"dzień"</string>
     <string name="days" msgid="4774547661021344602">"dni"</string>
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android się uruchamia…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optymalizacja pamięci."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optymalizowanie aplikacji <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Uruchamianie aplikacji."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Kończenie uruchamiania."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Działa <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nie można połączyć się z siecią Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ma powolne połączenie internetowe."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Zezwolić na połączenie?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s chce połączyć się z: %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikacja"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Uruchom Wi-Fi Direct. Spowoduje to wyłączenie klienta lub punktu dostępu Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Żądanie SS zostało zmienione na żądanie DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Żądanie SS zostało zmienione na żądanie USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Żądanie SS zostało zmienione na nowe żądanie SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 40e9313..b5e5484 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Há 1 hora"</item>
     <item quantity="other" msgid="2467273239587587569">"Há <xliff:g id="COUNT">%d</xliff:g> horas"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Últimos <xliff:g id="COUNT">%d</xliff:g> dias"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Último mês"</string>
     <string name="older" msgid="5211975022815554840">"Mais antiga"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"O Android está a iniciar…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"A otimizar o armazenamento."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"A otimizar a aplicação <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"A preparar o <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"A iniciar aplicações"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"A concluir o arranque."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível ligar a Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma ligação à internet fraca."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permitir ligação?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s pretende ligar a %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"A aplicação %1$s pretende estabelecer ligação à rede Wi-Fi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Uma aplicação"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar o Wi-Fi Direct. Esta opção desativará o cliente/zona Wi-Fi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"O pedido SS foi modificado para um pedido DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"O pedido SS foi modificado para um pedido USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"O pedido SS foi modificado para um novo pedido SS."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Porta periférica USB"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a11ba9d..5aab6e2 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 hora atrás"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> horas atrás"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Últimos <xliff:g id="COUNT">%d</xliff:g> dias"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Mês passado"</string>
     <string name="older" msgid="5211975022815554840">"Mais antigos"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"O Android está iniciando..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Otimizando o armazenamento."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando apps."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Concluindo a inicialização."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível se conectar a redes Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma conexão de baixa qualidade com a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permitir conexão?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s gostaria de se conectar a %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Um app"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar o Wi-Fi Direct. Isso desativará o ponto de acesso/cliente Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"A solicitação SS foi modificada para a solicitação DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"A solicitação SS foi modificada para a solicitação USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"A solicitação SS foi modificada para a nova solicitação SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 625f720..4bd2497 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"cu 1 oră în urmă"</item>
     <item quantity="other" msgid="2467273239587587569">"cu <xliff:g id="COUNT">%d</xliff:g> (de) ore în urmă"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Ultimele <xliff:g id="COUNT">%d</xliff:g> de zile"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Luna trecută"</string>
     <string name="older" msgid="5211975022815554840">"Mai vechi"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android pornește..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Se optimizează stocarea."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Se optimizează aplicaţia <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Se pornesc aplicaţiile."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Se finalizează pornirea."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Rulează <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nu se poate conecta la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" are o conexiune la internet slabă."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permiteți conectarea?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s dorește să se conecteze la %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"O aplicație"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Porniţi Wi-Fi Direct. Acest lucru va dezactiva clientul/hotspotul Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Solicitarea SS este modificată într-o solicitare DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Solicitarea SS este modificată într-o solicitare USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Solicitarea SS este modificată într-o nouă solicitare SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a768aa9..48e4a23 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 час назад"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ч. назад"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Последние <xliff:g id="COUNT">%d</xliff:g> дн."</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Прошлый месяц"</string>
     <string name="older" msgid="5211975022815554840">"Еще раньше"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Запуск Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимизация хранилища…"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизация приложения <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Запуск приложений."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Окончание загрузки..."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Приложение <xliff:g id="APP">%1$s</xliff:g> запущено"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не удалось подключиться к сети Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" – плохое интернет-соединение."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Разрешить подключение?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s запрашивает доступ на подключение к %2$s."</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Приложение"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Начать соединение через Wi-Fi Direct. Модуль Wi-Fi будет отключен."</string>
@@ -1846,7 +1847,7 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Запрашивать PIN-код для отключения блокировки"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запрашивать графический ключ для отключения блокировки"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string>
-    <string name="battery_saver_description" msgid="1960431123816253034">"Чтобы заряд батареи расходовался медленнее, режим энергосбережения уменьшает быстродействие устройства и ограничивает количество ресурсов, затрачиваемых на вибрацию, Геолокацию и большинство процессов обработки данных в фоновом режиме. Приложения, которые используют синхронизацию (например, для электронной почты и обмена SMS), могут не обновляться, пока вы их не откроете.\n\nКогда устройство заряжается, режим энергосбережения отключается автоматически."</string>
+    <string name="battery_saver_description" msgid="1960431123816253034">"Чтобы продлить время работы устройства от батареи, в режиме энергосбережения снижается производительность, а также ограничивается использование вибрации, геолокации и фоновой передачи данных. Данные, требующие синхронизации, могут обновляться только когда вы откроете приложение.\n\nРежим энергосбережения автоматически отключается во время зарядки устройства."</string>
     <string name="downtime_condition_summary" msgid="8761776337475705749">"До отключения режима (в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
     <string name="downtime_condition_line_one" msgid="8762708714645352010">"До отключения режима"</string>
   <plurals name="zen_mode_duration_minutes_summary">
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-запрос преобразован в DIAL-запрос."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-запрос преобразован в USSD-запрос."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-запрос преобразован в новый SS-запрос."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 3cde8f6..559e865 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1144,9 +1144,7 @@
     <item quantity="one" msgid="9150797944610821849">"පැය 1 කට පෙර"</item>
     <item quantity="other" msgid="2467273239587587569">"පැය <xliff:g id="COUNT">%d</xliff:g> කට පෙර"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"අන්තිම දවස් <xliff:g id="COUNT">%d</xliff:g>"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"අවසාන මාසය"</string>
     <string name="older" msgid="5211975022815554840">"පරණ"</string>
   <plurals name="num_days_ago">
@@ -1305,6 +1303,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android ආරම්භ කරමින්…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ආචයනය ප්‍රශස්තිකරණය කිරීම."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> කින් <xliff:g id="NUMBER_0">%1$d</xliff:g> වැනි යෙදුම ප්‍රශස්ත කරමින්."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> සූදානම් කරමින්."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"යෙදුම් ආරම්භ කරමින්."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ඇරඹුම අවසාන කරමින්."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ධාවනය වෙමින්"</string>
@@ -1350,7 +1349,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi වෙත සම්බන්ධ විය නොහැක"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" දුබල අන්තර්ජාල සම්බන්ධතාවයක් ඇත."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"සම්බන්ධතාවයට ඉඩ දෙන්නද?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%2$s වෙත සම්බන්ධවීමට %1$s කැමතිය"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"යෙදුම් %1$s ක් WiFi ජාලය %2$s වෙත සබැඳීමට කැමතියි"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"යෙදුම"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"ඍජු Wi-Fi"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ඍජු Wi-Fi ආරම්භ කරන්න. මෙය Wi-Fi සේවාදායක/හොට්ස්පොට් එක අක්‍රිය කරනු ඇත."</string>
@@ -1881,4 +1880,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS ඉල්ලීම DIAL ඉල්ලීම වෙත විකරණය කරන ලදී."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS ඉල්ලීම USSD ඉල්ලීම වෙත විකරණය කරන ලදී."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS ඉල්ලීම නව DIAL ඉල්ලීම වෙත විකරණය කරන ලදී."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"ඇන්ඩ්රොයිඩ්"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB පර්යන්ත තොට"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 4b56f04..f275f85 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"pred 1 hodinou"</item>
     <item quantity="other" msgid="2467273239587587569">"pred <xliff:g id="COUNT">%d</xliff:g> hodinami"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Posledných <xliff:g id="COUNT">%d</xliff:g> dní"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Minulý mesiac"</string>
     <string name="older" msgid="5211975022815554840">"Staršie"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Systém Android sa spúšťa…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimalizuje sa úložisko"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Prebieha optimalizácia aplikácie <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Prebieha spúšťanie aplikácií."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Prebieha dokončovanie spúšťania."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Spustená aplikácia: <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepodarilo sa pripojiť k sieti Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má nekvalitné internetové pripojenie."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Povoliť pripojenie?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"Zariadenie %1$s sa chce pripojiť k sieti %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikácia"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Priame pripojenie Wi-Fi"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Spustiť priame pripojenie siete Wi-Fi. Táto možnosť vypne sieť Wi-Fi v režime klient alebo hotspot."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Žiadosť SS bola upravená na žiadosť DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Žiadosť SS bola upravená na žiadosť USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Žiadosť SS bola upravená na novú žiadosť SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index dca7d4e..a53aac8 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"pred 1 uro"</item>
     <item quantity="other" msgid="2467273239587587569">"Pred <xliff:g id="COUNT">%d</xliff:g> urami"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Zadnjih <xliff:g id="COUNT">%d</xliff:g> dni"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Pretekli mesec"</string>
     <string name="older" msgid="5211975022815554840">"Starejše"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android se zaganja …"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimiziranje shrambe."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimiranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Zagon aplikacij."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Dokončevanje zagona."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> se izvaja"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Z omrežjem Wi-Fi se ni mogoče povezati"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima slabo internetno povezavo."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Ali dovolite vzpostavitev povezave?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s želi vzpostaviti povezavo s tem: %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Aplikacija"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Zaženite Wi-Fi Direct. S tem boste izklopili odjemalca/dostopno točko Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Zahteva SS je spremenjena v zahtevo DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Zahteva SS je spremenjena v zahtevo USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Zahteva SS je spremenjena v novo zahtevo SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index de9029f..b1510b6 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Пре сат времена"</item>
     <item quantity="other" msgid="2467273239587587569">"пре <xliff:g id="COUNT">%d</xliff:g> сата(и)"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"У последња(их) <xliff:g id="COUNT">%d</xliff:g> дана"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Прошлог месеца"</string>
     <string name="older" msgid="5211975022815554840">"Старије"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android се покреће…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Меморија се оптимизује."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизовање апликације <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Покретање апликација."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Завршавање покретања."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Апликација <xliff:g id="APP">%1$s</xliff:g> је покренута"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Није могуће повезати са Wi-Fi мрежом"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лошу интернет везу."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Желите ли да дозволите повезивање?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s жели да се повеже са мрежом %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Апликација"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Покрените Wi-Fi Direct. Тиме ћете искључити клијента/хотспот за Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS захтев је промењен у DIAL захтев."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS захтев је промењен у USSD захтев."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS захтев је промењен у нови SS захтев."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ad5c495..8fbf645 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"för 1 timme sedan"</item>
     <item quantity="other" msgid="2467273239587587569">"för <xliff:g id="COUNT">%d</xliff:g> timmar sedan"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"De senaste <xliff:g id="COUNT">%d</xliff:g> dagarna"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Föregående månad"</string>
     <string name="older" msgid="5211975022815554840">"Äldre"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android startar …"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Lagringsutrymmet optimeras."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerar app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> förbereds."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Appar startas."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Uppgraderingen är klar."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> körs"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Det gick inte att ansluta till Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dålig Internetanslutning."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Tillåt anslutning?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s vill ansluta till %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Appen %1$s vill ansluta till Wi-Fi-nätverket %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"En app"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi direkt"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Starta direkt Wi-Fi-användning. Detta inaktiverar Wi-Fi-användning med klient/trådlös surfzon."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS-begäran har ändrats till en DIAL-begäran."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS-begäran har ändrats till en USSD-begäran."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS-begäran har ändrats till en ny SS-begäran."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Perifer USB-port"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 2db8cd6..b2b21e3 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"Saa 1 iliyopita"</item>
     <item quantity="other" msgid="2467273239587587569">"Saa <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Siku <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Mwezi uliopita"</string>
     <string name="older" msgid="5211975022815554840">"Kuukuu zaidi"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Inaanzisha Android..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Inaboresha hifadhi."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Inaboresha programu <xliff:g id="NUMBER_0">%1$d</xliff:g> kutoka <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Programu zinaanza"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Inamaliza kuwasha."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> inaendelea"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Haikuweza kuunganisha kwa Mtandao-Hewa"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ina muunganisho duni wa Mtandao."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Ungepenga kuruhusu muunganisho?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s angependa kuunganisha kwenye %2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Programu"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Mtandao hewa Moja kwa moja"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Anzisha Wi-Fi Moja kwa Moja. Hii itazima mteja/mtandao-hewa wa Wi-Fi."</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Ombi la SS limerekebishwa na kuwa ombi la DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Ombi la SS limerekebishwa na kuwa ombi la USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Ombi la SS limerekebishwa na kuwa ombi jipya la SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 570671b..c8deaa7 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 மணிநேரம் முன்பு"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> மணிநேரத்திற்கு முன்பு"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"கடந்த <xliff:g id="COUNT">%d</xliff:g> நாட்கள்"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"சென்ற மாதம்"</string>
     <string name="older" msgid="5211975022815554840">"பழையது"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android துவங்குகிறது..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"சேமிப்பகத்தை உகந்ததாக்குகிறது."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> பயன்பாட்டை ஒருங்கிணைக்கிறது."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ஐத் தயார்செய்கிறது."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"பயன்பாடுகள் தொடங்கப்படுகின்றன."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"துவக்குதலை முடிக்கிறது."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> இயங்குகிறது"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"வைஃபை உடன் இணைக்க முடியவில்லை"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" இணைய இணைப்பு மோசமாக உள்ளது."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"இணைப்பை அனுமதிக்கவா?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s , %2$s உடன் இணைக்க விரும்புகிறது"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%2$s வைஃபை நெட்வொர்க்குடன், %1$s பயன்பாடு இணைக்க விரும்புகிறது"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"ஒரு பயன்பாடு"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"வைஃபை Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"வைஃபை Direct ஐத் தொடங்குக. இது வைஃபை க்ளையண்ட்/ஹாட்ஸ்பாட்டை முடக்கும்."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS கோரிக்கையானது DIAL கோரிக்கைக்கு மாற்றப்பட்டது."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS கோரிக்கையானது USSD கோரிக்கைக்கு மாற்றப்பட்டது."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS கோரிக்கையானது புதிய SS கோரிக்கைக்கு மாற்றப்பட்டது."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB பெரிபெரல் போர்ட்"</string>
 </resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 9975c71..27eeb88 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 గంట క్రితం"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> గంటల క్రితం"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"గత <xliff:g id="COUNT">%d</xliff:g> రోజులు"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"గత నెల"</string>
     <string name="older" msgid="5211975022815554840">"పాతది"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android ప్రారంభమవుతోంది…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"నిల్వను అనుకూలపరుస్తోంది."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> అనువర్తనాన్ని అనుకూలీకరిస్తోంది."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"అనువర్తనాలను ప్రారంభిస్తోంది."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"బూట్‌ను ముగిస్తోంది."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> అమలవుతోంది"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiకి కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" బలహీన ఇంటర్నెట్ కనెక్షన్‌ను కలిగి ఉంది."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"కనెక్షన్‌ని అనుమతించాలా?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s %2$sకి కనెక్ట్ చేయాలనుకుంటున్నారు"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s అనువర్తనం %2$s Wifi నెట్‌వర్క్‌కు కనెక్ట్ చేయాలనుకుంటోంది"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"ఒక అనువర్తనం"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Directను ప్రారంభించండి. దీని వలన Wi-Fi క్లయింట్/హాట్‌స్పాట్ ఆపివేయబడుతుంది."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS అభ్యర్థన డయల్ అభ్యర్థనగా సవరించబడింది."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS అభ్యర్థన USSD అభ్యర్థనగా సవరించబడింది."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS అభ్యర్థన కొత్త SS అభ్యర్థనగా సవరించబడింది."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB పెరిఫెరాల్ పోర్ట్"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f9bcd79..a4ebcec 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 ชั่วโมงที่ผ่านมา"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ชั่วโมงที่ผ่านมา"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> วันที่แล้ว"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"เดือนที่แล้ว"</string>
     <string name="older" msgid="5211975022815554840">"เก่ากว่า"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android กำลังเริ่มต้น…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"กำลังเพิ่มประสิทธิภาพพื้นที่จัดเก็บข้อมูล"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"กำลังเพิ่มประสิทธิภาพแอปพลิเคชัน <xliff:g id="NUMBER_0">%1$d</xliff:g> จาก <xliff:g id="NUMBER_1">%2$d</xliff:g> รายการ"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"กำลังเตรียม <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"กำลังเริ่มต้นแอปพลิเคชัน"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"เสร็จสิ้นการบูต"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> กำลังทำงาน"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ไม่สามารถเชื่อมต่อ WiFi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" มีสัญญาณอินเทอร์เน็ตไม่ดี"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"อนุญาตการเชื่อมต่อใช่ไหม"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s ต้องการเชื่อมต่อ %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"แอปพลิเคชัน %1$s ต้องการเชื่อมต่อเครือข่าย Wi-Fi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"แอปพลิเคชัน"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WiFi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"เริ่มการทำงาน WiFi Direct ซึ่งจะเป็นการปิดการทำงาน WiFi ไคลเอ็นต์/ฮอตสปอต"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"คำขอ SS ได้รับการแก้ไขให้เป็นคำขอ DIAL"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"คำขอ SS ได้รับการแก้ไขให้เป็นคำขอ USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"คำขอ SS ได้รับการแก้ไขให้เป็นคำขอ SS ใหม่"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"อุปกรณ์สำหรับต่อพอร์ต USB"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 2364e29..518d1f5 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 oras ang nakalipas"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> (na) oras ang nakalipas"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Huling <xliff:g id="COUNT">%d</xliff:g> (na) araw"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Nakaraang buwan"</string>
     <string name="older" msgid="5211975022815554840">"Mas luma"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Nagsisimula ang Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ino-optimize ang storage."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ino-optimize ang app <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Ihinahanda ang <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Sinisimulan ang apps."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Pagtatapos ng pag-boot."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Hindi makakonekta sa Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ay mayroong mahinang koneksyon sa Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Payagan ang kuneksyon?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"gustong kumonekta ni %1$s sa %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Gustong kumonekta ng application na %1$s sa Wifi Network na %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Isang application"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Simulan ang Wi-Fi Direct. I-o-off nito ang client/hotspot ng Wi-Fi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Ginawang DIAL request ang SS request."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Ginawang USSD request ang SS request."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Ginawang bagong SS request ang SS request."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB Peripheral Port"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 07d1ba7..e62423e 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -55,7 +55,7 @@
     <string name="mmiComplete" msgid="8232527495411698359">"MMI tamamlandı."</string>
     <string name="badPin" msgid="9015277645546710014">"Yazdığınız eski PIN doğru değil."</string>
     <string name="badPuk" msgid="5487257647081132201">"Yazdığınız PUK doğru değil."</string>
-    <string name="mismatchPin" msgid="609379054496863419">"Girdiğiniz PIN kodları eşleşmiyor"</string>
+    <string name="mismatchPin" msgid="609379054496863419">"Girdiğiniz PIN\'ler eşleşmiyor"</string>
     <string name="invalidPin" msgid="3850018445187475377">"4 ila 8 rakamdan oluşan bir PIN girin."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"8 veya daha uzun basamaklı bir PUK kodu yazın."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM kartınızın PUK kilidi devrede. Kilidi açmak için PUK kodunu yazın."</string>
@@ -192,7 +192,7 @@
     <string name="global_action_power_off" msgid="4471879440839879722">"Kapat"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hata raporu"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Hata raporu al"</string>
-    <string name="bugreport_message" msgid="398447048750350456">"Bu rapor, e-posta iletisi olarak göndermek üzere mevcut cihazınızın durumuyla ilgili bilgi toplar. Hata raporu başlatıldıktan sonra hazır olması biraz zaman alabilir, lütfen sabırlı olun."</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Bu rapor, e-posta iletisi olarak göndermek üzere cihazınızın şu anki durumuyla ilgili bilgi toplar. Hata raporu başlatıldıktan sonra hazır olması biraz zaman alabilir, lütfen sabırlı olun."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Sessiz mod"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ses KAPALI"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ses AÇIK"</string>
@@ -208,8 +208,8 @@
     <string name="managed_profile_label" msgid="6260850669674791528">"İş"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Size maliyet getiren hizmetler"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Size maliyet getirebilecek işlemler yapma."</string>
-    <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajlarınız"</string>
-    <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS mesajlarınızı, e-posta iletilerinizi ve diğer mesajlarınızı okuyup yazma."</string>
+    <string name="permgrouplab_messages" msgid="7521249148445456662">"İletileriniz"</string>
+    <string name="permgroupdesc_messages" msgid="7821999071003699236">"SMS, e-posta ve diğer iletilerinizi okuyup yazma."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Kişisel bilgileriniz"</string>
     <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"Sizinle ilgili, kişi kartınızda kayıtlı bilgilere doğrudan erişim."</string>
     <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"Sosyal bilgileriniz"</string>
@@ -269,13 +269,13 @@
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD karta erişin."</string>
     <string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"Erişilebilirlik özellikleri"</string>
     <string name="permgroupdesc_accessibilityFeatures" msgid="4205196881678144335">"Engelli kullanıcılara yardımcı olan teknolojinin istekte bulunabileceği özellikler."</string>
-    <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pencere içeriğini alın"</string>
-    <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Etkileşim kurduğunuz pencerenin içeriğini inceleyin."</string>
-    <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Dokunarak Keşfet\'i açın"</string>
+    <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Pencere içeriğini alma"</string>
+    <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Etkileşim kurduğunuz pencerenin içeriğini inceler."</string>
+    <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Dokunarak Keşfet\'i açma"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"Dokunulan öğeler sesli olarak okunur ve ekranı keşfetmek için hareketler kullanılabilir."</string>
-    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Gelişmiş web erişilebilirliğini açın"</string>
+    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Gelişmiş web erişilebilirliğini açma"</string>
     <string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Uygulamanın erişilebilirliğini artırmak için komut dosyaları yüklenebilir."</string>
-    <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Yazdığınız metni izleyin"</string>
+    <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Yazdığınız metni izleme"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Kredi kartı ve şifre gibi kişisel bilgiler içerir."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"durum çubuğunu devre dışı bırak veya değiştir"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
@@ -290,25 +290,25 @@
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"giden çağrıları yeniden yönlendir"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Uygulamaya, giden bir çağrının numarası çevrilirken çağrıyı farklı bir numaraya yönlendirme ya da tamamen kapatma seçeneğiyle birlikte numarayı görme izni verir."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"kısa mesajları al (SMS)"</string>
-    <string name="permdesc_receiveSms" msgid="6424387754228766939">"Uygulamaya SMS mesajlarını alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen mesajları takip edip size göstermeden silebileceği anlamına gelir."</string>
+    <string name="permdesc_receiveSms" msgid="6424387754228766939">"Uygulamaya SMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"kısa mesajları (MMS) al"</string>
-    <string name="permdesc_receiveMms" msgid="533019437263212260">"Uygulamaya MMS mesajlarını alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen mesajları takip edip size göstermeden silebileceği anlamına gelir."</string>
+    <string name="permdesc_receiveMms" msgid="533019437263212260">"Uygulamaya MMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"acil durum yayınlarını al"</string>
     <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Uygulamaya, acil yayın mesajları alma ve işleme izni verir. Bu izin, sadece sistem uygulamaları için kullanılabilir."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"hücre yayını mesajlarını oku"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string>
-    <string name="permlab_sendSms" msgid="5600830612147671529">"SMS mesajları gönder"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"Uygulamaya SMS mesajları gönderme izni verir. Bu durum beklenmeyen ödemelere neden olabilir. Kötü amaçlı uygulamalar onayınız olmadan mesajlar göndererek sizi zarara uğratabilir."</string>
+    <string name="permlab_sendSms" msgid="5600830612147671529">"SMS iletileri gönder"</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"Uygulamaya SMS iletisi gönderme izni verir. Bu durum beklenmeyen ödemelere neden olabilir. Kötü amaçlı uygulamalar onayınız olmadan iletiler göndererek sizi zarara uğratabilir."</string>
     <string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"mesajla yanıtla etkinlikleri gönder"</string>
     <string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"Uygulamaya, gelen çağrıları mesajla yanıtlama etkinliklerini işlemek üzere diğer mesajlaşma uygulamalarına istek gönderme izni verir."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"kısa mesajlarımı (SMS veya MMS) oku"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Uygulamaya tabletinizde veya SIM kartta saklanan SMS mesajlarını okuma izni verir. Bu izin, uygulamanın tüm SMS mesajlarını içeriğinden veya gizliliğinden bağımsız olarak okumasına olanak sağlar."</string>
-    <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Uygulamaya, TV\'nizde veya SIM kartta depolanmış SMS mesajlarını okuma izni verir. Bu izin, uygulamanın içeriğe veya gizliliğe bakılmaksızın tüm SMS mesajlarını okumasına olanak sağlar."</string>
-    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Uygulamaya telefonunuzda veya SIM kartta saklanan SMS mesajlarını okuma izni verir. Bu izin, uygulamanın tüm SMS mesajlarını içeriğinden veya gizliliğinden bağımsız olarak okumasına olanak sağlar."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Uygulamaya tabletinizde veya SIM kartta saklanan SMS iletilerini okuma izni verir. Bu izin, uygulamanın tüm SMS iletilerini içeriğinden veya gizliliğinden bağımsız olarak okumasına olanak sağlar."</string>
+    <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Uygulamaya, TV\'nizde veya SIM kartta depolanmış SMS iletilerini okuma izni verir. Bu izin, uygulamanın içeriğe veya gizliliğe bakılmaksızın tüm SMS iletilerini okumasına olanak sağlar."</string>
+    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Uygulamaya telefonunuzda veya SIM kartta saklanan SMS iletilerini okuma izni verir. Bu izin, uygulamanın tüm SMS iletilerini içeriğinden veya gizliliğinden bağımsız olarak okumasına olanak sağlar."</string>
     <string name="permlab_writeSms" msgid="3216950472636214774">"kısa mesajlarımı (SMS veya MMS) düzenle"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"Uygulamaya, tabletinizde veya SIM kartınızda depolanan SMS mesajlarına yazma izni verir. Kötü amaçlı uygulamalar mesajlarınızı silebilir."</string>
-    <string name="permdesc_writeSms" product="tv" msgid="955871498983538187">"Uygulamaya, TV\'niz ya da SIM kartınızda saklanan SMS mesajlarına yazma izni verir. Kötü amaçlı uygulamalar mesajlarınızı silebilir."</string>
-    <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Uygulamaya, telefonunuzdaki veya SIM kartınızdaki SMS mesajlarına yazma izni verir. Kötü amaçlı uygulamalar mesajlarınızı silebilir."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"Uygulamaya, tabletinizde veya SIM kartınızda depolanan SMS iletilerine yazma izni verir. Kötü amaçlı uygulamalar iletilerinizi silebilir."</string>
+    <string name="permdesc_writeSms" product="tv" msgid="955871498983538187">"Uygulamaya, TV\'niz ya da SIM kartınızda saklanan SMS iletilerine yazma izni verir. Kötü amaçlı uygulamalar iletilerinizi silebilir."</string>
+    <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Uygulamaya, telefonunuzdaki veya SIM kartınızdaki SMS iletilerine yazma izni verir. Kötü amaçlı uygulamalar iletilerinizi silebilir."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"kısa mesajları (WAP) al"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Uygulamaya WAP mesajlarını alma ve işleme izni verir. Buna, size gönderilen mesajları takip edip size göstermeden silebilme izni de dahildir."</string>
     <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth iletilerini al (MAP)"</string>
@@ -370,7 +370,7 @@
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"paket ile kaldırılan yayını gönder"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"Uygulamaya, bir uygulama paketinin kaldırıldığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar çalışan diğer uygulamaları kapatmak için bunu kullanabilir."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"SMS ile alınan yayın gönder"</string>
-    <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Uygulamaya, SMS mesajı alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte SMS mesajları göndermek için bunu kullanabilir."</string>
+    <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Uygulamaya, SMS iletisi alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte SMS iletileri göndermek için bunu kullanabilir."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH ile alınan yayın gönder"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Uygulamaya, WAP PUSH mesajı alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte MMS bildirimleri oluşturmak veya bir web sayfasının içeriğini sessiz şekilde zararlı öğelerle değiştirmek için bunu kullanabilir."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"çalışan işlem sayısını sınırla"</string>
@@ -526,15 +526,15 @@
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"sosyal akışınızı okuma"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Uygulamaya size veya arkadaşlarınıza ait sosyal güncellemelere erişme ve bunları senkronize etme izni verir. Bilgi paylaşırken dikkatli olun. Bu izin, uygulamanın sosyal ağlarda sizinle arkadaşlarınız arasındaki iletişimi, gizliliğine bakılmaksızın okumasına olanak sağlar. Not: Bu izin tüm sosyal ağlar için geçerli olmayabilir."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"sosyal akışınıza yazma"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Uygulamaya arkadaşlarınızın sosyal güncellemelerini gösterme izni verir. Bilgi paylaşırken dikkatli olun -- Bu uygulama bir arkadaşınızdan geliyormuş gibi görünen mesajlar oluşturabilir. Not: Bu izin, tüm sosyal ağlarda geçerli olmayabilir."</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Uygulamaya arkadaşlarınızın sosyal güncellemelerini gösterme izni verir. Bilgi paylaşırken dikkatli olun -- Bu uygulama bir arkadaşınızdan geliyormuş gibi görünen iletiler oluşturabilir. Not: Bu izin, tüm sosyal ağlarda geçerli olmayabilir."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"takvim etkinliklerini ve gizli bilgileri oku"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Uygulamaya, arkadaşlarınızın ve iş arkadaşlarınızın etkinlikleri de olmak üzere tabletinizde depolanan tüm takvim etkinliklerini okuma izni verir. Bu izin, uygulamanın takvim verilerinizi gizliliğine ve hassaslığına bakmaksızın paylaşmasına ve kaydetmesine olanak sağlayabilir."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"Uygulamaya, arkadaşlarınızın ve iş arkadaşlarınızın etkinlikleri dahil olmak üzere TV\'nizde kayıtlı tüm takvim etkinliklerini okuma izni verir. Bu da uygulamanın gizlilik ve duyarlılık dikkate alınmaksızın takvim verilerinizi paylaşmasına veya kaydetmesine olanak sağlayabilir."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Uygulamaya, arkadaşlarınızın ve iş arkadaşlarınızın etkinlikleri de dahil olmak üzere telefonunuzda depolanan tüm takvim etkinliklerini okuma izni verir. Bu izin, uygulamanın takvim verilerinizi gizliliğine ve hassaslığına bakmaksızın paylaşmasına ve kaydetmesine olanak sağlayabilir."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"sahibin bilgisi olmadan takvim etkinlikleri ekle veya mevcut etkinlikleri değiştir ve misafirlere e-posta gönder"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Uygulamaya, arkadaşlarınızın veya iş arkadaşlarınızın etkinlikleri de dahil olmak üzere tabletinizde değiştirebileceğiniz etkinlikleri ekleme, kaldırma ve değiştirme izni verir. Bu izin, uygulamanın takvim sahiplerinden geliyormuş gibi görünen mesajlar göndermesine veya etkinlikleri sahibinden habersiz olarak değiştirmesine olanak sağlar."</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Uygulamaya, arkadaşlarınızın veya iş arkadaşlarınızın etkinlikleri de dahil olmak üzere tabletinizde değiştirebileceğiniz etkinlikleri ekleme, kaldırma ve değiştirme izni verir. Bu izin, uygulamanın takvim sahiplerinden geliyormuş gibi görünen iletiler göndermesine veya etkinlikleri sahibinden habersiz olarak değiştirmesine olanak sağlar."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"Uygulamaya, arkadaşlarınızın veya iş arkadaşlarınızın etkinlikleri de dahil olmak üzere cihazınızda değiştirebileceğiniz etkinlikleri ekleme, kaldırma ve değiştirme izni verir. Bu izin, uygulamanın, takvim sahiplerinden gelmiş gibi görünen iletiler göndermesine veya takvim sahiplerinin bilgisi olmadan etkinlikleri değiştirmesine olanak sağlayabilir."</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Uygulamaya, arkadaşlarınızın veya iş arkadaşlarınızın etkinlikleri de dahil olmak üzere telefonunuzda değiştirebileceğiniz etkinlikleri ekleme, kaldırma ve değiştirme izni verir. Bu izin, uygulamanın takvim sahiplerinden geliyormuş gibi görünen mesajlar göndermesine veya etkinlikleri sahibinden habersiz olarak değiştirmesine olanak sağlar."</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Uygulamaya, arkadaşlarınızın veya iş arkadaşlarınızın etkinlikleri de dahil olmak üzere telefonunuzda değiştirebileceğiniz etkinlikleri ekleme, kaldırma ve değiştirme izni verir. Bu izin, uygulamanın takvim sahiplerinden geliyormuş gibi görünen iletiler göndermesine veya etkinlikleri sahibinden habersiz olarak değiştirmesine olanak sağlar."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"test için sahte konum kaynakları"</string>
     <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Test amacıyla veya yeni bir konum sağlayıcı yüklemek için sahte konum kaynakları oluşturma. Bu izin, uygulamanın GPS veya konum sağlayıcıları gibi diğer konum kaynakları tarafından döndürülen konum ve/veya durum bilgisini geçersiz kılmasına olanak sağlar."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ek konum sağlayıcı komutlarına eriş"</string>
@@ -747,9 +747,9 @@
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Uygulamaya, o anda senkronize olan özet akışları ile ilgili bilgi alma izni verir."</string>
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"abone olunan yayınları yazma"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Uygulamaya, o anda senkronize edilmiş özet akışlarını değiştirme izni verir. Kötü amaçlı uygulamalar senkronize edilmiş özet akışlarını değiştirebilir."</string>
-    <string name="permlab_readDictionary" msgid="4107101525746035718">"sözlüğe eklediğim terimleri oku"</string>
+    <string name="permlab_readDictionary" msgid="4107101525746035718">"sözlüğe eklediğiniz terimleri okuma"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Uygulamaya, kullanıcının kullanıcı sözlüğünde depolamış olabileceği kelimeleri, adları ve kelime öbeklerini okuma izni verir."</string>
-    <string name="permlab_writeDictionary" msgid="2183110402314441106">"kullanıcı tanımlı sözlüğe kelime ekle"</string>
+    <string name="permlab_writeDictionary" msgid="2183110402314441106">"kullanıcı tanımlı sözlüğe kelime ekleme"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Uygulamaya, kullanıcı sözlüğüne yeni kelimeler yazma izni verir."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"USB belleğini okuma"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"SD kartımın içeriğini oku"</string>
@@ -817,11 +817,11 @@
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Ekran kilidini açarken yapılan yanlış şifre girme denemelerini izle ve çok fazla sayıda yanlış şifre girme denemesi yapılmışsa tableti kilitle veya tabletteki tüm verileri sil."</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Ekran kilidi açılırken girilen hatalı şifre sayısını takip etme ve çok fazla sayıda hatalı şifre girildiğinde TV\'yi kilitleme veya TV\'nin tüm verilerini silme."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Ekran kilidini açarken yapılan yanlış şifre girişi denemelerini izle ve çok sayıda yanlış şifre girişi denemesi yapılmışsa telefonu kilitle veya telefonun tüm verilerini sil."</string>
-    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ekran kilidini açma şifresini değiştir"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ekran kilidini açma şifresini değiştirme"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Ekran kilidini açma şifresini değiştirme."</string>
-    <string name="policylab_forceLock" msgid="2274085384704248431">"Ekranı kilitle"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Ekranı kilitleme"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Ekranın nasıl ve ne zaman kilitlendiğini denetleme."</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Tüm verileri sil"</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Tüm verileri silme"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek tabletteki verileri uyarıda bulunmadan silme."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Fabrika ayarlarına sıfırlama yoluyla TV\'nin verilerini uyarı vermeksizin silme."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek telefondaki verileri uyarıda bulunmadan silme."</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 saat önce"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> saat önce"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Son <xliff:g id="COUNT">%d</xliff:g> gün"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Son ay"</string>
     <string name="older" msgid="5211975022815554840">"Daha eski"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android başlatılıyor…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Depolama optimize ediliyor."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> uygulama optimize ediliyor."</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Uygulamalar başlatılıyor"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Açılış tamamlanıyor."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> çalışıyor"</string>
@@ -1348,12 +1348,13 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kablosuz bağlantısı kurulamadı"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" İnternet bağlantısı zayıf."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Bağlantıya izin verilsin mi?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s, %2$s ile bağlantı kurmak istiyor"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Bir uygulama"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Kablosuz Doğrudan Bağlantı"</string>
-    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Kablosuz Doğrudan Bağlantıyı başlat. Bu işlem, Kablosuz istemci/hotspot kullanımını kapatacak."</string>
-    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Kablosuz Doğrudan bağlantı başlatılamadı."</string>
-    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Kablosuz Doğrudan özelliği açık"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Kablosuz Doğrudan Bağlantı\'yı başlat. Bu işlem, Kablosuz istemci/hotspot kullanımını kapatacak."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Kablosuz Doğrudan Bağlantı başlatılamadı."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Kablosuz Doğrudan Bağlantı özelliği açık"</string>
     <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Ayarlar için dokunun"</string>
     <string name="accept" msgid="1645267259272829559">"Kabul et"</string>
     <string name="decline" msgid="2112225451706137894">"Reddet"</string>
@@ -1367,11 +1368,11 @@
     <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile bağlantıya sahipken TV\'nizin Kablosuz bağlantısı geçici olarak kesilecek."</string>
     <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefon <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken Kablosuz ağ bağlantısı geçici olarak kesilecektir"</string>
     <string name="select_character" msgid="3365550120617701745">"Karakter ekle"</string>
-    <string name="sms_control_title" msgid="7296612781128917719">"SMS mesajları gönderiliyor"</string>
-    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; çok sayıda SMS mesajı gönderiyor. Bu uygulamanın mesaj göndermeye devam etmesine izin veriyor musunuz?"</string>
+    <string name="sms_control_title" msgid="7296612781128917719">"SMS iletileri gönderiliyor"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; çok sayıda SMS iletisi gönderiyor. Bu uygulamanın ileti göndermeye devam etmesine izin veriyor musunuz?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"İzin ver"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Reddet"</string>
-    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; adresine bir mesaj göndermek istiyor."</string>
+    <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; adresine bir ileti göndermek istiyor."</string>
     <string name="sms_short_code_details" msgid="5873295990846059400">"Bu işlem, mobil hesabınızdan "<b>"ödeme alınmasına neden olabilir"</b>"."</string>
     <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Bu işlem, mobil hesabınızdan ödeme alınmasına neden olacak."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Gönder"</string>
@@ -1524,7 +1525,7 @@
     <string name="submit" msgid="1602335572089911941">"Gönder"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Araba modu etkin"</string>
     <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Araba modundan çıkmak için dokunun."</string>
-    <string name="tethered_notification_title" msgid="3146694234398202601">"Doğrudan bağlantı veya ortak erişim noktası etkin"</string>
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering veya hotspot etkin"</string>
     <string name="tethered_notification_message" msgid="6857031760103062982">"Kurulum için dokunun."</string>
     <string name="back_button_label" msgid="2300470004503343439">"Geri"</string>
     <string name="next_button_label" msgid="1080555104677992408">"İleri"</string>
@@ -1847,8 +1848,8 @@
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Pil tasarrufu özelliği, pil ömrünü iyileştirmeye yardımcı olmak için cihazın performansını düşürür, titreşimi, konum hizmetlerini ve arka plan verilerinin çoğunu sınırlar. Senkronizasyona dayalı olarak çalışan e-posta, mesajlaşma uygulamaları ve diğer uygulamalar, bunları açmadığınız sürece güncellenmeyebilir.\n\nCihazınız şarj olurken pil tasarrufu otomatik olarak kapatılır."</string>
-    <string name="downtime_condition_summary" msgid="8761776337475705749">"Kesinti süreniz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> saatinde sona erene kadar"</string>
-    <string name="downtime_condition_line_one" msgid="8762708714645352010">"Kullanım dışı kalma durumunuz bitene kadar"</string>
+    <string name="downtime_condition_summary" msgid="8761776337475705749">"Bildirim istenmeyen zaman <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> saatinde sona erene kadar"</string>
+    <string name="downtime_condition_line_one" msgid="8762708714645352010">"Bildirim istenmeyen zaman bitene kadar"</string>
   <plurals name="zen_mode_duration_minutes_summary">
     <item quantity="one" msgid="3177683545388923234">"Bir dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
     <item quantity="other" msgid="2787867221129368935">"%1$d dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS isteği DIAL isteği olarak değiştirildi."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS isteği USSD isteği olarak değiştirildi."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS isteği yeni SS isteği olarak değiştirildi."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 79281b3..47c364b 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -71,7 +71,7 @@
     <string name="ClirMmi" msgid="7784673673446833091">"Вихід. ід. абонента"</string>
     <string name="ColpMmi" msgid="3065121483740183974">"Ідентифікатор під’єднаної лінії"</string>
     <string name="ColrMmi" msgid="4996540314421889589">"Обмеження ідентифікатора під’єднаної лінії"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"Переадрес. виклику"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"Переадресація виклику"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Паралел. виклик"</string>
     <string name="BaMmi" msgid="455193067926770581">"Заборона викл."</string>
     <string name="PwdMmi" msgid="7043715687905254199">"Зміна пароля"</string>
@@ -879,9 +879,9 @@
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
     <string name="phoneTypeCustom" msgid="1644738059053355820">"Указати"</string>
-    <string name="phoneTypeHome" msgid="2570923463033985887">"Дом."</string>
+    <string name="phoneTypeHome" msgid="2570923463033985887">"Домашній"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"Мобільний"</string>
-    <string name="phoneTypeWork" msgid="8863939667059911633">"Роб."</string>
+    <string name="phoneTypeWork" msgid="8863939667059911633">"Робочий"</string>
     <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Роб. факс"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Дом. факс"</string>
     <string name="phoneTypePager" msgid="7582359955394921732">"Пейджер"</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 год. тому"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> год. тому"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Остан. <xliff:g id="COUNT">%d</xliff:g> дн."</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Останній міс."</string>
     <string name="older" msgid="5211975022815554840">"Давніше"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Запуск ОС Android…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимізація пам’яті."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимізація програми <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Підготовка додатка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Запуск програм."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Завершення завантаження."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Працює <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" має погане з’єднання з Інтернетом."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Дозволити з’єднання?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s хоче під’єднатися до %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Додаток %1$s хоче під’єднатися до мережі Wi-Fi \"%2$s\""</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Додаток"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Запустити Wi-Fi Direct. Це вимкне з’єднання Wi-Fi клієнт/точка доступу."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Запит SS перетворено на запит DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Запит SS перетворено на запит USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Запит SS перетворено на новий запит SS."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Периферійний USB-порт"</string>
 </resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 7f8a88e..ae7acf2 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 گھنٹہ پہلے"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> گھنٹے پہلے"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"آخری <xliff:g id="COUNT">%d</xliff:g> دن"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"پچھلے مہینے"</string>
     <string name="older" msgid="5211975022815554840">"پرانا"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"‏Android شروع ہو رہا ہے…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"اسٹوریج کو بہترین بنایا جا رہا ہے۔"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g> کو بہتر بنایا جا رہا ہے۔"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> تیار ہو رہی ہے۔"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ایپس شروع ہو رہی ہیں۔"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"بوٹ مکمل ہو رہا ہے۔"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> چل رہی ہے"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏Wi-Fi سے مربوط نہیں ہو سکا"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" اس میں ایک کمزور انٹرنیٹ کنکشن ہے۔"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"کنکشن کی اجازت دیں؟"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"‏%2$s سے ‎%1$s‎ منسلک ہونا چاہے گا"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"‏ایپلیکیشن ‎%1$s Wifi نیٹ ورک ‎%2$s سے منسلک ہونا چاہتی ہے"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"ایک ایپلیکیشن"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"‏Wi-Fi ڈائریکٹ"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"‏Wi-Fi ڈائرکٹ شروع کریں۔ یہ Wi-Fi کلائنٹ/ہاٹ اسپاٹ کو آف کردے گا۔"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"‏SS درخواست میں ترمیم کر کے DIAL درخواست بنا دی گئی ہے۔"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"‏SS درخواست میں ترمیم کر کے USSD درخواست بنا دی گئی ہے۔"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"‏SS درخواست میں ترمیم کر کے نئی SS درخواست بنا دی گئی ہے۔"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"‏USB ملحقہ پورٹ"</string>
 </resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 306e4b2..51d24ed 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 soat oldin"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> soat oldin"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"O‘tgan <xliff:g id="COUNT">%d</xliff:g> kun"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"O‘tgan oy"</string>
     <string name="older" msgid="5211975022815554840">"Eskiroq"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android ishga tushmoqda…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Xotira optimallashtirilmoqda."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ilovalar optimallashtirilmoqda (<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>)."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> tayyorlanmoqda."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ilovalar ishga tushirilmoqda."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Tizimni yuklashni tugatish."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ishlamoqda"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi’ga ulana olmadi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tezligi past Internetga ulangan."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Ulanishga ruxsat berilsinmi?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s quyidagiga ulanmoqchi: %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s ilovasi %2$s Wi-Fi tarmog‘iga ulanmoqchi"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Ilova"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct’ni ishga tushirish. Bu Wi-Fi mijoz/ulanish nuqtasini o‘chiradi."</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS so‘rovi DIAL so‘roviga o‘zgartirildi."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS so‘rovi USSD so‘roviga o‘zgartirildi."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS so‘rovi yangi SS so‘roviga o‘zgartirildi."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Tashqi USB porti"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index e361bad..a6172d7 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 giờ trước"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> giờ trước"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> ngày trước"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Tháng trước"</string>
     <string name="older" msgid="5211975022815554840">"Cũ hơn"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android đang khởi động..."</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Tối ưu hóa lưu trữ."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Đang tối ưu hóa ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> trong tổng số <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"Đang chuẩn bị <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Khởi động ứng dụng."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Hoàn tất khởi động."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> đang hoạt động"</string>
@@ -1348,9 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Không thể kết nối với Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" có kết nối Internet không tốt."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Cho phép kết nối?"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for wifi_connect_alert_message (8930084523889618078) -->
-    <skip />
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Ứng dụng %1$s muốn kết nối với Mạng Wifi %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Ứng dụng"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Khởi động Wi-Fi Direct. Việc này sẽ tắt hoạt động của ứng dụng khách/điểm phát sóng Wi-Fi."</string>
@@ -1881,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Yêu cầu SS được sửa đổi thành yêu cầu DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Yêu cầu SS được sửa đổi thành yêu cầu USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Yêu cầu SS được sửa đổi thành yêu cầu SS mới."</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"Cổng ngoại vi USB"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 4a03e7b..d225e3f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -970,7 +970,7 @@
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"重试"</string>
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"重试"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超过“人脸解锁”尝试次数上限"</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"没有SIM卡"</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"没有 SIM 卡"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板电脑中没有SIM卡。"</string>
     <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"电视中没有 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手机中无SIM卡"</string>
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1小时前"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>小时前"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"过去<xliff:g id="COUNT">%d</xliff:g>天"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"上个月"</string>
     <string name="older" msgid="5211975022815554840">"往前"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android 正在启动…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在优化存储空间。"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在优化第<xliff:g id="NUMBER_0">%1$d</xliff:g>个应用(共<xliff:g id="NUMBER_1">%2$d</xliff:g>个)。"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在启动应用。"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"即将完成启动。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g>正在运行"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到WLAN"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互联网连接状况不佳。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"要允许连接吗?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s想要连接到%2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"一款应用"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WLAN直连"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"启动WLAN直连。此操作将会关闭WLAN客户端/热点。"</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS 请求已修改为 DIAL 请求。"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS 请求已修改为 USSD 请求。"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS 请求已修改为新的 SS 请求。"</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index bb39491..210e955 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 小時前"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"最近 <xliff:g id="COUNT">%d</xliff:g> 天"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"上個月"</string>
     <string name="older" msgid="5211975022815554840">"較舊"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android 正在啟動…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在優化儲存空間。"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在優化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"正在準備升級「<xliff:g id="APPNAME">%1$s</xliff:g>」。"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在啟動應用程式。"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"啟動完成。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"正在執行 <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互聯網連線欠佳。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"允許連線?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s 要求連線至 %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"「%1$s」應用程式要求連線至 WiFi 網路 %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"應用程式"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"啟動 Wi-Fi Direct,這會關閉 Wi-Fi 使用者端/熱點。"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS 要求已修改為 DIAL 要求。"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS 要求已修改為 USSD 要求。"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS 要求已修改為新的 SS 要求。"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB 週邊連接埠"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 507205a..97d878a 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 小時以前"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"最近 <xliff:g id="COUNT">%d</xliff:g> 天"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"上個月"</string>
     <string name="older" msgid="5211975022815554840">"較舊"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,7 @@
     <string name="android_start_title" msgid="8418054686415318207">"Android 正在啟動…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在對儲存空間進行最佳化處理。"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在最佳化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
+    <string name="android_preparing_apk" msgid="8162599310274079154">"正在準備升級「<xliff:g id="APPNAME">%1$s</xliff:g>」。"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在啟動應用程式。"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"啟動完成。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> 執行中"</string>
@@ -1348,7 +1347,7 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 的網際網路連線狀況不佳。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"允許連線?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"%1$s 要求連線至 %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="6451273376815958922">"「%1$s」應用程式要求連線至 WiFi 網路 %2$s"</string>
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"應用程式"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"啟動 Wi-Fi Direct 作業,這會關閉 Wi-Fi 用戶端/無線基地台作業。"</string>
@@ -1879,4 +1878,6 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS 要求已改為 DIAL 要求。"</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS 要求已改為 USSD 要求。"</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS 要求已改為新的 SS 要求。"</string>
+    <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
+    <string name="usb_midi_peripheral_model_name" msgid="1959288763942653301">"USB 週邊連接埠"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1222904..f9eb830 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1142,9 +1142,7 @@
     <item quantity="one" msgid="9150797944610821849">"1 ihora eledlule"</item>
     <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> amahora adlule"</item>
   </plurals>
-  <plurals name="last_num_days">
-    <item quantity="other" msgid="3069992808164318268">"Izinsuku zokugcina ezingu- <xliff:g id="COUNT">%d</xliff:g>"</item>
-  </plurals>
+    <!-- no translation found for last_num_days:one (7555846096746489821) -->
     <string name="last_month" msgid="3959346739979055432">"Inyanga edlule"</string>
     <string name="older" msgid="5211975022815554840">"Okudala kakhulu"</string>
   <plurals name="num_days_ago">
@@ -1303,6 +1301,8 @@
     <string name="android_start_title" msgid="8418054686415318207">"I-Android iyaqala…"</string>
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ikhulisa isitoreji."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ukubeka ezingeni eliphezulu <xliff:g id="NUMBER_0">%1$d</xliff:g> uhlelo lokusebenza <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for android_preparing_apk (8162599310274079154) -->
+    <skip />
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Qalisa izinhlelo zokusebenza."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Qedela ukuqala kabusha."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> iyasebenza"</string>
@@ -1348,7 +1348,8 @@
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ayikwazanga ukuxhuma kwi-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" inoxhumano oluphansi lwe-inthanethi."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vumela ukuxhumeka?"</string>
-    <string name="wifi_connect_alert_message" msgid="8930084523889618078">"U-%1$s angathanda ukuxhumeka ku-%2$s"</string>
+    <!-- no translation found for wifi_connect_alert_message (6451273376815958922) -->
+    <skip />
     <string name="wifi_connect_default_application" msgid="7143109390475484319">"Uhlelo lokusebenza"</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"I-Wi-Fi Eqondile"</string>
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Qala ukusebenza kwe-Wi-Fi Okuqondile. Lokhu kuzocima ikhasimende le-Wi-Fi/Ukusebenza okwe-hotspot"</string>
@@ -1879,4 +1880,8 @@
     <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"Isicelo se-SS siguqulelwe kusicelo se-DIAL."</string>
     <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"Isicelo se-SS siguqulelwe kusicelo se-USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"Isicelo se-SS siguqulelwe kusicelo esisha se-SS."</string>
+    <!-- no translation found for usb_midi_peripheral_manufacturer_name (7176526170008970168) -->
+    <skip />
+    <!-- no translation found for usb_midi_peripheral_model_name (1959288763942653301) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 39c42ee..b90ac65 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1952,6 +1952,16 @@
 
         <!-- Whether to clip window content to the outline of the window background. -->
         <attr name="windowClipToOutline" format="boolean" />
+
+        <!-- If set, the status bar will be drawn such that it is compatible with a light
+             status bar background.
+             <p>For this to take effect, the window must be drawing the system bar backgrounds with
+             {@link android.R.attr#windowDrawsSystemBarBackgrounds} and the status bar must not
+             have been requested to be translucent with
+             {@link android.R.attr#windowTranslucentStatus}.
+             Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_STATUS_BAR} on
+             the decor view. -->
+        <attr name="windowHasLightStatusBar" format="boolean" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -2631,6 +2641,8 @@
     <declare-styleable name="Include">
         <attr name="id" />
         <attr name="visibility" />
+        <attr name="layout_width" />
+        <attr name="layout_height" />
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -4338,6 +4350,10 @@
         <attr name="popupAnimationStyle" format="reference" />
         <!-- Whether the popup window should overlap its anchor view. -->
         <attr name="overlapAnchor" format="boolean" />
+        <!-- Transition used to move views into the popup window. -->
+        <attr name="popupEnterTransition" format="reference" />
+        <!-- Transition used to move views out of the popup window. -->
+        <attr name="popupExitTransition" format="reference" />
     </declare-styleable>
     <declare-styleable name="ListPopupWindow">
         <!-- Amount of pixels by which the drop down should be offset vertically. -->
@@ -5074,14 +5090,31 @@
 
     <!-- Describes an item (or child) of a LayerDrawable. -->
     <declare-styleable name="LayerDrawableItem">
-        <!-- Left coordinate of the layer. -->
+        <!-- Left inset to apply to the layer. -->
         <attr name="left" />
-        <!-- Top coordinate of the layer. -->
+        <!-- Top inset to apply to the layer. -->
         <attr name="top" />
-        <!-- Right coordinate of the layer. -->
+        <!-- Right inset to apply to the layer. -->
         <attr name="right" />
-        <!-- Bottom coordinate of the layer. -->
+        <!-- Bottom inset to apply to the layer. -->
         <attr name="bottom" />
+        <!-- Start inset to apply to the layer. Overrides {@code left} or
+             {@code right} depending on layout direction. -->
+        <attr name="start" format="dimension" />
+        <!-- End inset to apply to the layer. Overrides {@code left} or
+             {@code right} depending on layout direction. -->
+        <attr name="end" format="dimension" />
+        <!-- Width of the layer. Defaults to the layer's intrinsic width. -->
+        <attr name="width" />
+        <!-- Height of the layer. Defaults to the layer's intrinsic height -->
+        <attr name="height" />
+        <!-- Gravity used to align the layer within its container. If no value
+             is specified, the default behavior depends on whether an explicit
+             width or height has been set, If no dimension is set, gravity in
+             that direction defaults to {@code fill_horizontal} or
+             {@code fill_vertical}; otherwise, it defaults to {@code left} or
+             {@code top}. -->
+        <attr name="gravity" />
         <!-- Drawable used to render the layer. -->
         <attr name="drawable" />
         <!-- Identifier of the layer. This can be used to retrieve the layer
@@ -5963,11 +5996,11 @@
              set when a view is enabled. -->
         <attr name="state_enabled" format="boolean" />
         <!-- State identifier indicating that the object <var>may</var> display a check mark.
-             See {@link R.attr#state_checked} for the identifier that indicates whether it is
+             See {@link android.R.attr#state_checked} for the identifier that indicates whether it is
              actually checked. -->
         <attr name="state_checkable" format="boolean"/>
         <!-- State identifier indicating that the object is currently checked.  See
-             {@link R.attr#state_checkable} for an additional identifier that can indicate if
+             {@link android.R.attr#state_checkable} for an additional identifier that can indicate if
              any object may ever display a check, regardless of whether state_checked is
              currently set. -->
         <attr name="state_checked" format="boolean"/>
@@ -7257,8 +7290,34 @@
     <declare-styleable name="Switch">
         <!-- Drawable to use as the "thumb" that switches back and forth. -->
         <attr name="thumb" />
+        <!-- Tint to apply to the thumb. -->
+        <attr name="thumbTint" />
+        <!-- Blending mode used to apply the thumb tint. -->
+        <attr name="thumbTintMode" />
         <!-- Drawable to use as the "track" that the switch thumb slides within. -->
         <attr name="track" format="reference" />
+        <!-- Tint to apply to the track. -->
+        <attr name="trackTint" format="color" />
+        <!-- Blending mode used to apply the track tint. -->
+        <attr name="trackTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+            <!-- Combines the tint and drawable color and alpha channels, clamping the
+                 result to valid color values. Saturate(S + D) -->
+            <enum name="add" value="16" />
+        </attr>
         <!-- Text to use when the switch is in the checked/"on" state. -->
         <attr name="textOn" />
         <!-- Text to use when the switch is in the unchecked/"off" state. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0c3fb9a..84609ca 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1012,6 +1012,20 @@
          <p>The default value of this attribute is <code>false</code>. -->
     <attr name="resumeWhilePausing" format="boolean" />
 
+    <!-- Indicates that it is okay for this activity to be resized to any dimension. Intended for a
+         multi-window device where there can be multiple activities of various sizes on the screen
+         at the same time.
+
+         <p>The default value is <code>false</code> for applications with
+         <code>targetSdkVersion</code> lesser than {@link android.os.Build.VERSION_CODES#MNC} and
+         <code>true</code> otherwise.
+
+         <p>NOTE: A task's root activity value is applied to all additional activities launched in
+         the task. That is if the root activity of a task is resizeable then the system will treat
+         all other activities in the task as resizeable and will not if the root activity isn't
+         resizeable. -->
+    <attr name="resizeableActivity" format="boolean" />
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -1020,7 +1034,7 @@
          to avoid name collisions.  For example, applications published
          by Google could have names of the form
          <code>com.google.app.<em>appname</em></code>
-         
+
          <p>Inside of the manifest tag, may appear the following tags
          in any order: {@link #AndroidManifestPermission permission},
          {@link #AndroidManifestPermissionGroup permission-group},
@@ -1039,7 +1053,7 @@
         <attr name="sharedUserLabel" />
         <attr name="installLocation" />
     </declare-styleable>
-    
+
     <!-- The <code>application</code> tag describes application-level components
          contained in the package, as well as general application
          attributes.  Many of the attributes you can supply here (such
@@ -1047,7 +1061,7 @@
          and allowTaskReparenting) serve
          as default values for the corresponding attributes of components
          declared inside of the application.
-         
+
          <p>Inside of this element you specify what the application contains,
          using the elements {@link #AndroidManifestProvider provider},
          {@link #AndroidManifestService service},
@@ -1698,6 +1712,7 @@
         <attr name="autoRemoveFromRecents" />
         <attr name="relinquishTaskIdentity" />
         <attr name="resumeWhilePausing" />
+        <attr name="resizeableActivity" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9945c63..e2a0ec9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2608,6 +2608,13 @@
        =============================================================== -->
   <eat-comment />
 
+  <public type="attr" name="trackTint" />
+  <public type="attr" name="trackTintMode" />
+  <public type="attr" name="resizeableActivity" />
+  <public type="attr" name="start" />
+  <public type="attr" name="end" />
+  <public type="attr" name="windowHasLightStatusBar" />
+
   <public type="style" name="Widget.Material.Button.Colored" />
 
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index efdc3c8..ab6dbff 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3397,6 +3397,7 @@
 
     <!-- This is used to express that something occurred within the last X days (e.g., Last 7 days). -->
     <plurals name="last_num_days">
+        <item quantity="one">Last <xliff:g id="count">%d</xliff:g> day</item>
         <item quantity="other">Last <xliff:g id="count">%d</xliff:g> days</item>
     </plurals>
 
@@ -3748,6 +3749,9 @@
         <xliff:g id="number" example="123">%1$d</xliff:g> of
         <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
 
+    <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk pre boot broadcast -->
+    <string name="android_preparing_apk">Preparing <xliff:g id="appname">%1$s</xliff:g>.</string>
+
     <!-- [CHAR LIMIT=NONE] Message to show in upgrading dialog when reached the point of starting apps. -->
     <string name="android_upgrading_starting_apps">Starting apps.</string>
 
@@ -3853,7 +3857,7 @@
     <!-- title for this message -->
     <string name="wifi_connect_alert_title">Allow connection?</string>
     <!-- message explaining who is connecting to what -->
-    <string name="wifi_connect_alert_message">%1$s would like to connect to %2$s</string>
+    <string name="wifi_connect_alert_message">Application %1$s would like to connect to Wifi Network %2$s</string>
     <!-- default application in case name can not be found -->
     <string name="wifi_connect_default_application">An application</string>
 
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 4329809..777924f 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -88,7 +88,7 @@
     </style>
 
     <style name="Preference.Material.DialogPreference.EditTextPreference">
-        <item name="dialogLayout">@layout/preference_dialog_edittext</item>
+        <item name="dialogLayout">@layout/preference_dialog_edittext_material</item>
     </style>
 
     <style name="Preference.Material.RingtonePreference">
@@ -464,7 +464,7 @@
 
     <!-- Colored bordered ink button -->
     <style name="Widget.Material.Button.Colored">
-        <item name="backgroundTint">@color/btn_material_accent</item>
+        <item name="backgroundTint">@color/btn_colored_material</item>
     </style>
 
     <!-- Small bordered ink button -->
@@ -481,8 +481,7 @@
 
     <!-- Colored borderless ink button -->
     <style name="Widget.Material.Button.Borderless.Colored">
-        <item name="textColor">?attr/colorAccent</item>
-        <item name="stateListAnimator">@anim/disabled_anim_material</item>
+        <item name="textColor">@color/btn_colored_text_material</item>
     </style>
 
     <!-- Alert dialog button bar button -->
@@ -770,6 +769,9 @@
         <item name="dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
         <item name="popupBackground">@drawable/popup_background_material</item>
         <item name="popupElevation">@dimen/floating_window_z</item>
+        <item name="popupAnimationStyle">@empty</item>
+        <item name="popupEnterTransition">@transition/popup_window_enter</item>
+        <item name="popupExitTransition">@transition/popup_window_exit</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="overlapAnchor">true</item>
@@ -780,11 +782,7 @@
     </style>
 
     <style name="Widget.Material.Spinner.DropDown"/>
-
-    <style name="Widget.Material.Spinner.DropDown.ActionBar">
-        <item name="background">@drawable/spinner_background_material</item>
-        <item name="overlapAnchor">true</item>
-    </style>
+    <style name="Widget.Material.Spinner.DropDown.ActionBar" />
 
     <style name="Widget.Material.Spinner.Underlined">
         <item name="background">@drawable/spinner_textfield_background_material</item>
@@ -847,7 +845,9 @@
         <item name="dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
         <item name="popupBackground">@drawable/popup_background_material</item>
         <item name="popupElevation">@dimen/floating_window_z</item>
-        <item name="popupAnimationStyle">@style/Animation.Material.Popup</item>
+        <item name="popupAnimationStyle">@empty</item>
+        <item name="popupEnterTransition">@transition/popup_window_enter</item>
+        <item name="popupExitTransition">@transition/popup_window_exit</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 607744f..9c1fd07 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1514,6 +1514,7 @@
   <java-symbol type="layout" name="screen_title" />
   <java-symbol type="layout" name="screen_title_icons" />
   <java-symbol type="string" name="system_ui_date_pattern" />
+  <java-symbol type="string" name="android_preparing_apk" />
   <java-symbol type="string" name="android_start_title" />
   <java-symbol type="string" name="android_upgrading_title" />
   <java-symbol type="string" name="bugreport_title" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 7804dd2..18c83b4 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -75,7 +75,7 @@
     <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
 
     <!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
-    <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}" />
+    <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215" />
 
     <!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
     <shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}" />
diff --git a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
index e7f4bad..e5a92bf 100644
--- a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
+++ b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
@@ -11,7 +11,7 @@
 
     public void testSmallList() throws Exception {
         final int objectCount = 100;
-        List<SmallObject> list = new ArrayList<>();
+        List<SmallObject> list = new ArrayList<SmallObject>();
         for (int i = 0; i < objectCount; i++) {
             list.add(new SmallObject(i * 2, (i * 2) + 1));
         }
@@ -20,7 +20,7 @@
 
         Parcel parcel = Parcel.obtain();
         try {
-            parcel.writeParcelable(new ParceledListSlice<>(list), 0);
+            parcel.writeParcelable(new ParceledListSlice<SmallObject>(list), 0);
             parcel.setDataPosition(0);
             slice = parcel.readParcelable(getClass().getClassLoader());
         } finally {
@@ -56,7 +56,7 @@
         final int thresholdBytes = 256 * 1024;
         final int objectCount = thresholdBytes / measureLargeObject();
 
-        List<LargeObject> list = new ArrayList<>();
+        List<LargeObject> list = new ArrayList<LargeObject>();
         for (int i = 0; i < objectCount; i++) {
             list.add(new LargeObject(
                     i * 5,
@@ -71,7 +71,7 @@
 
         Parcel parcel = Parcel.obtain();
         try {
-            parcel.writeParcelable(new ParceledListSlice<>(list), 0);
+            parcel.writeParcelable(new ParceledListSlice<LargeObject>(list), 0);
             parcel.setDataPosition(0);
             slice = parcel.readParcelable(getClass().getClassLoader());
         } finally {
@@ -95,7 +95,7 @@
      * Test that only homogeneous elements may be unparceled.
      */
     public void testHomogeneousElements() throws Exception {
-        List<BaseObject> list = new ArrayList<>();
+        List<BaseObject> list = new ArrayList<BaseObject>();
         list.add(new LargeObject(0, 1, 2, 3, 4));
         list.add(new SmallObject(5, 6));
         list.add(new SmallObject(7, 8));
diff --git a/core/tests/coretests/src/android/net/StaticIpConfigurationTest.java b/core/tests/coretests/src/android/net/StaticIpConfigurationTest.java
new file mode 100644
index 0000000..59f780f
--- /dev/null
+++ b/core/tests/coretests/src/android/net/StaticIpConfigurationTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
+import android.os.Parcel;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static org.junit.Assert.*;
+
+
+public class StaticIpConfigurationTest extends TestCase {
+
+    private static final String ADDRSTR = "192.0.2.2/25";
+    private static final LinkAddress ADDR = new LinkAddress(ADDRSTR);
+    private static final InetAddress GATEWAY = IpAddress("192.0.2.1");
+    private static final InetAddress OFFLINKGATEWAY = IpAddress("192.0.2.129");
+    private static final InetAddress DNS1 = IpAddress("8.8.8.8");
+    private static final InetAddress DNS2 = IpAddress("8.8.4.4");
+    private static final InetAddress DNS3 = IpAddress("4.2.2.2");
+    private static final String IFACE = "eth0";
+
+    private static InetAddress IpAddress(String addr) {
+        return InetAddress.parseNumericAddress(addr);
+    }
+
+    private void checkEmpty(StaticIpConfiguration s) {
+        assertNull(s.ipAddress);
+        assertNull(s.gateway);
+        assertNull(s.domains);
+        assertEquals(0, s.dnsServers.size());
+    }
+
+    private boolean isEqual(StaticIpConfiguration s1, StaticIpConfiguration s2) {
+        return s1.equals(s2);
+    }
+
+    private void assertEquals(StaticIpConfiguration s1, StaticIpConfiguration s2) {
+        assertTrue(isEqual(s1, s2));
+    }
+
+    private void assertNotEquals(StaticIpConfiguration s1, StaticIpConfiguration s2) {
+        assertFalse(isEqual(s1, s2));
+    }
+
+    private StaticIpConfiguration makeTestObject() {
+        StaticIpConfiguration s = new StaticIpConfiguration();
+        s.ipAddress = ADDR;
+        s.gateway = GATEWAY;
+        s.dnsServers.add(DNS1);
+        s.dnsServers.add(DNS2);
+        s.dnsServers.add(DNS3);
+        s.domains = "google.com";
+        return s;
+    }
+
+    @SmallTest
+    public void testConstructor() {
+        StaticIpConfiguration s = new StaticIpConfiguration();
+        checkEmpty(s);
+    }
+
+    @SmallTest
+    public void testCopyAndClear() {
+        StaticIpConfiguration empty = new StaticIpConfiguration((StaticIpConfiguration) null);
+        checkEmpty(empty);
+
+        StaticIpConfiguration s1 = makeTestObject();
+        StaticIpConfiguration s2 = new StaticIpConfiguration(s1);
+        assertEquals(s1, s2);
+        s2.clear();
+        assertEquals(empty, s2);
+    }
+
+    @SmallTest
+    public void testHashCodeAndEquals() {
+        HashSet<Integer> hashCodes = new HashSet();
+        hashCodes.add(0);
+
+        StaticIpConfiguration s = new StaticIpConfiguration();
+        // Check that this hash code is nonzero and different from all the ones seen so far.
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        s.ipAddress = ADDR;
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        s.gateway = GATEWAY;
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        s.dnsServers.add(DNS1);
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        s.dnsServers.add(DNS2);
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        s.dnsServers.add(DNS3);
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        s.domains = "example.com";
+        assertTrue(hashCodes.add(s.hashCode()));
+
+        assertFalse(s.equals(null));
+        assertEquals(s, s);
+
+        StaticIpConfiguration s2 = new StaticIpConfiguration(s);
+        assertEquals(s, s2);
+
+        s.ipAddress = new LinkAddress(DNS1, 32);
+        assertNotEquals(s, s2);
+
+        s2 = new StaticIpConfiguration(s);
+        s.domains = "foo";
+        assertNotEquals(s, s2);
+
+        s2 = new StaticIpConfiguration(s);
+        s.gateway = DNS2;
+        assertNotEquals(s, s2);
+
+        s2 = new StaticIpConfiguration(s);
+        s.dnsServers.add(DNS3);
+        assertNotEquals(s, s2);
+    }
+
+    @SmallTest
+    public void testToLinkProperties() {
+        LinkProperties expected = new LinkProperties();
+        expected.setInterfaceName(IFACE);
+
+        StaticIpConfiguration s = new StaticIpConfiguration();
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        final RouteInfo connectedRoute = new RouteInfo(new IpPrefix(ADDRSTR), null, IFACE);
+        s.ipAddress = ADDR;
+        expected.addLinkAddress(ADDR);
+        expected.addRoute(connectedRoute);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        s.gateway = GATEWAY;
+        RouteInfo defaultRoute = new RouteInfo(new IpPrefix("0.0.0.0/0"), GATEWAY, IFACE);
+        expected.addRoute(defaultRoute);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        s.gateway = OFFLINKGATEWAY;
+        expected.removeRoute(defaultRoute);
+        defaultRoute = new RouteInfo(new IpPrefix("0.0.0.0/0"), OFFLINKGATEWAY, IFACE);
+        expected.addRoute(defaultRoute);
+
+        RouteInfo gatewayRoute = new RouteInfo(new IpPrefix("192.0.2.129/32"), null, IFACE);
+        expected.addRoute(gatewayRoute);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        s.dnsServers.add(DNS1);
+        expected.addDnsServer(DNS1);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        s.dnsServers.add(DNS2);
+        s.dnsServers.add(DNS3);
+        expected.addDnsServer(DNS2);
+        expected.addDnsServer(DNS3);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        s.domains = "google.com";
+        expected.setDomains("google.com");
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        s.gateway = null;
+        expected.removeRoute(defaultRoute);
+        expected.removeRoute(gatewayRoute);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+
+        // Without knowing the IP address, we don't have a directly-connected route, so we can't
+        // tell if the gateway is off-link or not and we don't add a host route. This isn't a real
+        // configuration, but we should at least not crash.
+        s.gateway = OFFLINKGATEWAY;
+        s.ipAddress = null;
+        expected.removeLinkAddress(ADDR);
+        expected.removeRoute(connectedRoute);
+        expected.addRoute(defaultRoute);
+        assertEquals(expected, s.toLinkProperties(IFACE));
+    }
+
+    private StaticIpConfiguration passThroughParcel(StaticIpConfiguration s) {
+        Parcel p = Parcel.obtain();
+        StaticIpConfiguration s2 = null;
+        try {
+            s.writeToParcel(p, 0);
+            p.setDataPosition(0);
+            s2 = StaticIpConfiguration.CREATOR.createFromParcel(p);
+        } finally {
+            p.recycle();
+        }
+        assertNotNull(s2);
+        return s2;
+    }
+
+    @SmallTest
+    public void testParceling() {
+        StaticIpConfiguration s = makeTestObject();
+        StaticIpConfiguration s2 = passThroughParcel(s);
+        assertEquals(s, s2);
+    }
+}
+
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 0002ba7..7bf5f65 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -33,7 +33,8 @@
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifeq ($(LOCAL_USE_JACK),true)
+
+ifdef LOCAL_USE_JACK
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
@@ -41,10 +42,11 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/multidexlegacyandexception/Test.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index c9dbb57..416c238 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -33,7 +33,7 @@
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifeq ($(LOCAL_USE_JACK),true)
+ifdef LOCAL_USE_JACK
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
@@ -41,12 +41,14 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/multidexlegacytestapp/Test.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
+endif
 
 ## The application with a full main dex
 include $(CLEAR_VARS)
@@ -67,7 +69,7 @@
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2)
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifeq ($(LOCAL_USE_JACK),true)
+ifdef LOCAL_USE_JACK
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
@@ -75,9 +77,11 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList2): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/multidexlegacytestapp/Test.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList2)
+endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
index 16e396b..83ead4b 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
@@ -36,9 +36,10 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
index c62238b..d706ca9 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -32,7 +32,8 @@
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifeq ($(LOCAL_USE_JACK),true)
+
+ifdef LOCAL_USE_JACK
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
@@ -40,9 +41,11 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
+endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
index 8c0c5d5..99b2a8b 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -32,7 +32,8 @@
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifeq ($(LOCAL_USE_JACK),true)
+
+ifdef LOCAL_USE_JACK
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
@@ -40,9 +41,11 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
index 002c1cc..3ee1c22 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -32,7 +32,8 @@
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifeq ($(LOCAL_USE_JACK),true)
+
+ifdef LOCAL_USE_JACK
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
@@ -40,10 +41,12 @@
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_USE_JACK
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
 	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
+endif
 
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 5265f20..4e03108 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -57,7 +57,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on January 5, 2015.
+<p style="clear:both"><em>Data collected during a 7-day period ending on February 2, 2015.
 <br/>Any versions with less than 0.1% distribution are not shown.</em>
 </p>
 
@@ -88,7 +88,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on January 5, 2015.
+<p style="clear:both"><em>Data collected during a 7-day period ending on February 2, 2015.
 
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
@@ -108,7 +108,7 @@
 
 
 <img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0&chf=bg%2Cs%2C00000000&chd=t%3A69.9%2C30.1&chco=c4df9b%2C6fad0c&cht=p&chs=400x250" />
+src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0&chf=bg%2Cs%2C00000000&chd=t%3A68.9%2C31.1&chco=c4df9b%2C6fad0c&cht=p&chs=400x250" />
 
 
 <p>To declare which version of OpenGL ES your application requires, you should use the {@code
@@ -127,17 +127,17 @@
 </tr>
 <tr>
 <td>2.0</td>
-<td>69.9%</td>
+<td>68.9%</td>
 </tr>
 <tr>
 <td>3.0</td>
-<td>30.1%</td>
+<td>31.1%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on January 5, 2015</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on February 2, 2015</em></p>
 
 
 
@@ -155,7 +155,7 @@
 var VERSION_DATA =
 [
   {
-    "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chco=c4df9b%2C6fad0c&chd=t%3A0.4%2C7.8%2C6.7%2C46.0%2C39.1&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat",
+    "chart": "//chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A0.4%2C7.4%2C6.4%2C44.5%2C39.7%2C1.6&chco=c4df9b%2C6fad0c&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop&chs=500x250&cht=p",
     "data": [
       {
         "api": 8,
@@ -165,32 +165,37 @@
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "7.8"
+        "perc": "7.4"
       },
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "6.7"
+        "perc": "6.4"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "19.2"
+        "perc": "18.4"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "20.3"
+        "perc": "19.8"
       },
       {
         "api": 18,
         "name": "Jelly Bean",
-        "perc": "6.5"
+        "perc": "6.3"
       },
       {
         "api": 19,
         "name": "KitKat",
-        "perc": "39.1"
+        "perc": "39.7"
+      },
+      {
+        "api": 21,
+        "name": "Lollipop",
+        "perc": "1.6"
       }
     ]
   }
@@ -203,29 +208,29 @@
     "data": {
       "Large": {
         "hdpi": "0.6",
-        "ldpi": "0.6",
-        "mdpi": "5.4",
-        "tvdpi": "2.3",
+        "ldpi": "0.5",
+        "mdpi": "5.1",
+        "tvdpi": "2.2",
         "xhdpi": "0.6"
       },
       "Normal": {
-        "hdpi": "37.5",
-        "mdpi": "8.8",
+        "hdpi": "38.3",
+        "mdpi": "8.7",
         "tvdpi": "0.1",
-        "xhdpi": "18.4",
-        "xxhdpi": "16.3"
+        "xhdpi": "18.8",
+        "xxhdpi": "15.9"
       },
       "Small": {
         "ldpi": "4.8"
       },
       "Xlarge": {
         "hdpi": "0.3",
-        "mdpi": "3.7",
+        "mdpi": "3.5",
         "xhdpi": "0.6"
       }
     },
-    "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chd=t%3A5.4%2C17.9%2C2.4%2C38.4%2C19.6%2C16.3&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
-    "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chd=t%3A4.6%2C9.5%2C81.1%2C4.8&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall"
+    "densitychart": "//chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A5.3%2C17.3%2C2.3%2C39.2%2C20.0%2C15.9&chco=c4df9b%2C6fad0c&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chs=400x250&cht=p",
+    "layoutchart": "//chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A4.4%2C9.0%2C81.8%2C4.8&chco=c4df9b%2C6fad0c&chl=Xlarge%7CLarge%7CNormal%7CSmall&chs=400x250&cht=p"
   }
 ];
 
@@ -305,7 +310,7 @@
   },
   {
     "api":21,
-    "link":"<a href='/about/versions/android-5.0.html'>4.4</a>",
+    "link":"<a href='/about/versions/android-5.0.html'>5.0</a>",
     "codename":"Lollipop"
   }
 ];
diff --git a/docs/html/images/tv/app-browse.png b/docs/html/images/tv/app-browse.png
new file mode 100644
index 0000000..7670713
--- /dev/null
+++ b/docs/html/images/tv/app-browse.png
Binary files differ
diff --git a/docs/html/images/tv/card-view.png b/docs/html/images/tv/card-view.png
new file mode 100644
index 0000000..5e907de
--- /dev/null
+++ b/docs/html/images/tv/card-view.png
Binary files differ
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index e74d46a..af6f6b8 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -481,14 +481,14 @@
 
 <ul>
 <li>GNOME or KDE desktop</li>
-<li>GNU C Library (glibc) 2.11 or later</li>
+<li>GNU C Library (glibc) 2.15 or later</li>
 <li>2 GB RAM minimum, 4 GB RAM recommended</li>
 <li>400 MB hard disk space</li>
 <li>At least 1 GB for Android SDK, emulator system images, and caches</li>
 <li>1280 x 800 minimum screen resolution</li>
 <li>Oracle&reg;  Java Development Kit (JDK) 7 </li>
 </ul>
-<p>Tested on Ubuntu&reg;  12.04, Precise Pangolin (64-bit distribution capable of running
+<p>Tested on Ubuntu&reg;  14.04, Trusty Tahr (64-bit distribution capable of running
 32-bit applications).</p>
 
 
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index 42240b9..5bdd4e2 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -122,7 +122,7 @@
 mobile devices, including: </p>
 
 <ul>
-  <li>An ARMv5 CPU and the corresponding memory-management unit (MMU)</li>
+  <li>An ARMv5, ARMv7, or x86 CPU</li>
   <li>A 16-bit LCD display</li>
   <li>One or more keyboards (a Qwerty-based keyboard and associated Dpad/Phone
 buttons)</li>
diff --git a/docs/html/training/basics/intents/sending.jd b/docs/html/training/basics/intents/sending.jd
index 4698ba1..b9463e4 100644
--- a/docs/html/training/basics/intents/sending.jd
+++ b/docs/html/training/basics/intents/sending.jd
@@ -153,7 +153,8 @@
 
 <pre>
 PackageManager packageManager = {@link android.content.Context#getPackageManager()};
-List&lt;ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
+List<ResolveInfo> activities = packageManager.queryIntentActivities(intent,
+        PackageManager.MATCH_DEFAULT_ONLY);
 boolean isIntentSafe = activities.size() > 0;
 </pre>
 
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index f5999a5..c59d8ff 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -951,6 +951,10 @@
               Creating a Catalog Browser</a>
           </li>
           <li>
+            <a href="<?cs var:toroot ?>training/tv/playback/card.html">
+              Providing a Card View</a>
+          </li>
+          <li>
             <a href="<?cs var:toroot ?>training/tv/playback/details.html"
                ja-lang="詳細ビューをビルドする">
               Building a Details View</a>
@@ -1883,4 +1887,4 @@
     buildToggleLists();
     changeNavLang(getLangPref());
 //-->
-</script>
+</script>
\ No newline at end of file
diff --git a/docs/html/training/tv/playback/card.jd b/docs/html/training/tv/playback/card.jd
new file mode 100644
index 0000000..8ac75fd
--- /dev/null
+++ b/docs/html/training/tv/playback/card.jd
@@ -0,0 +1,156 @@
+page.title=Providing a Card View
+page.tags="card"
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>This lesson teaches you to</h2>
+  <ol>
+    <li><a href="#presenter">Create a Card Presenter</a></li>
+    <li><a href="#card-view">Create a Card View</a></li>
+  </ol>
+  <h2>Try it out</h2>
+  <ul>
+    <li><a class="external-link" href="https://github.com/googlesamples/androidtv-Leanback">Android
+    Leanback sample app</a></li>
+  </ul>
+</div>
+</div>
+
+<p>In the previous lesson, you created a catalog browser, implemented in a browse fragment, that
+displays a list of media items. In this lesson, you create the card views for your media items and
+present them in the browse fragment.</p>
+
+<p>The {@link android.support.v17.leanback.widget.BaseCardView} class and subclasses display the meta
+data associated with a media item. The {@link android.support.v17.leanback.widget.ImageCardView}
+class used in this lesson displays an image for the content along with the media item's title.</p>
+
+<p>This lesson describes code from the <a href="https://github.com/googlesamples/androidtv-Leanback">
+Android Leanback sample app</a>, available on GitHub. Use this sample code to start your own
+app.</p>
+
+<img itemprop="image" src="{@docRoot}images/tv/app-browse.png" alt="App main screen"/>
+<p class="img-caption"><b>Figure 1.</b> The <a href="https://github.com/googlesamples/androidtv-Leanback">
+Leanback sample app</a> browse fragment with a card presenter displaying card view objects.</p>
+
+<h2 id="presenter">Create a Card Presenter</h2>
+
+<p>A {@link android.support.v17.leanback.widget.Presenter} generates views and binds objects to them
+on demand. In the browse fragment where your app presents its content to the user, you create a
+{@link android.support.v17.leanback.widget.Presenter} for the content cards and pass it to the adapter
+that adds the content to the screen. In the following code, the <code>CardPresenter</code> is created
+in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android.support.v4.content.Loader, java.lang.Object) onLoadFinished()}
+callback of the {@link android.support.v4.app.LoaderManager}.</p>
+
+<pre>
+&#64;Override
+public void onLoadFinished(Loader&lt;HashMap&lt;String, List&lt;Movie&gt;&gt;&gt; arg0,
+                           HashMap&lt;String, List&lt;Movie&gt;&gt; data) {
+
+    mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+    CardPresenter cardPresenter = new CardPresenter();
+
+    int i = 0;
+
+    for (Map.Entry&lt;String, List&lt;Movie&gt;&gt; entry : data.entrySet()) {
+        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
+        List&lt;Movie&gt; list = entry.getValue();
+
+        for (int j = 0; j &lt; list.size(); j++) {
+            listRowAdapter.add(list.get(j));
+        }
+        HeaderItem header = new HeaderItem(i, entry.getKey(), null);
+        i++;
+        mRowsAdapter.add(new ListRow(header, listRowAdapter));
+    }
+
+    HeaderItem gridHeader = new HeaderItem(i, getString(R.string.more_samples),
+            null);
+
+    GridItemPresenter gridPresenter = new GridItemPresenter();
+    ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
+    gridRowAdapter.add(getString(R.string.grid_view));
+    gridRowAdapter.add(getString(R.string.error_fragment));
+    gridRowAdapter.add(getString(R.string.personal_settings));
+    mRowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));
+
+    setAdapter(mRowsAdapter);
+
+    updateRecommendations();
+}
+</pre>
+
+<h2 id="card-view">Create a Card View</h2>
+
+<p>In this step, you build the card presenter with a view holder for the card view that describes
+your media content items. Note that each presenter must only create one view type. If you have two
+different card view types then you need two different card presenters.</p>
+
+<p>In the {@link android.support.v17.leanback.widget.Presenter}, implement an
+{@link android.support.v17.leanback.widget.Presenter#onCreateViewHolder(android.view.ViewGroup) onCreateViewHolder()}
+callback that creates a view holder that can be used to display a content item.</p>
+
+<pre>
+&#64;Override
+public class CardPresenter extends Presenter {
+
+    private Context mContext;
+    private static int CARD_WIDTH = 313;
+    private static int CARD_HEIGHT = 176;
+    private Drawable mDefaultCardImage;
+
+    &#64;Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent) {
+        mContext = parent.getContext();
+        mDefaultCardImage = mContext.getResources().getDrawable(R.drawable.movie);
+...
+</pre>
+
+<p>In the {@link android.support.v17.leanback.widget.Presenter#onCreateViewHolder(android.view.ViewGroup)
+onCreateViewHolder()} method, create a card view for content items. The sample below uses an
+{@link android.support.v17.leanback.widget.ImageCardView}.</p>
+
+<p>When a card is selected, the default behavior expands it to a larger size. If you want to designate
+a different color for the selected card, call {@link android.support.v17.leanback.widget.BaseCardView#setSelected(boolean)
+setSelected()}
+as shown here.</p>
+
+<pre>
+...
+    ImageCardView cardView = new ImageCardView(mContext) {
+        &#64;Override
+        public void setSelected(boolean selected) {
+            int selected_background = mContext.getResources().getColor(R.color.detail_background);
+            int default_background = mContext.getResources().getColor(R.color.default_background);
+            int color = selected ? selected_background : default_background;
+            findViewById(R.id.info_field).setBackgroundColor(color);
+            super.setSelected(selected);
+        }
+    };
+...
+</pre>
+
+<p>When the user opens your app, the {@link android.support.v17.leanback.widget.Presenter.ViewHolder}
+displays the <code>CardView</code> objects for your content items. You need to set these to receive
+focus from the D-pad controller by calling {@link android.view.View#setFocusable(boolean) setFocusable(true)}
+and {@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode(true)}.</p>
+
+<pre>
+...
+    cardView.setFocusable(true);
+    cardView.setFocusableInTouchMode(true);
+    return new ViewHolder(cardView);
+}
+</pre>
+
+<p>When the user selects the {@link android.support.v17.leanback.widget.ImageCardView}, it expands
+to reveal its text area with the background color you specify, as shown in figure 2.</p>
+
+<img itemprop="image" src="{@docRoot}images/tv/card-view.png" alt="App card view"/>
+<p class="img-caption"><b>Figure 2.</b> The <a href="https://github.com/googlesamples/androidtv-Leanback">
+Leanback sample app</a> image card view when selected.</p>
+
+
diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd
index 5427d48..0e9c5ec 100644
--- a/docs/html/training/tv/playback/index.jd
+++ b/docs/html/training/tv/playback/index.jd
@@ -56,6 +56,9 @@
     <dd>Learn how to use the Leanback support library to build a browsing interface for media
       catalogs.</dd>
 
+  <dt><b><a href="details.html">Providing a Card View</a></b></dt>
+    <dd>Learn how to use the Leanback support library to build a card view for content items.</dd>
+
   <dt><b><a href="details.html">Building a Details View</a></b></dt>
     <dd>Learn how to use the Leanback support library to build a details page for media items.</dd>
 
diff --git a/docs/html/training/tv/start/layouts.jd b/docs/html/training/tv/start/layouts.jd
index 177ea7a..a378096 100644
--- a/docs/html/training/tv/start/layouts.jd
+++ b/docs/html/training/tv/start/layouts.jd
@@ -119,8 +119,8 @@
 
 <p>
   Avoid screen elements being clipped due to overscan and by incorporating a 10% margin
-  on all sides of your layout. This translates into a 27dp margin on the left and right edges and
-  a 48dp margin on the top and bottom of your base layouts for activities. The following
+  on all sides of your layout. This translates into a 48dp margin on the left and right edges and
+  a 27dp margin on the top and bottom of your base layouts for activities. The following
   example layout demonstrates how to set these margins in the root layout for a TV app:
 </p>
 
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 206c959..48ee6fa 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -23,7 +23,7 @@
 @Deprecated
 public class AvoidXfermode extends Xfermode {
 
-    // these need to match the enum in SkAvoidXfermode.h on the native side
+    // these need to match the enum in AvoidXfermode.h on the native side
     public enum Mode {
         AVOID   (0),    //!< draw everywhere except on the opColor
         TARGET  (1);    //!< draw only on top of the opColor
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index fa9af2a..39272b9 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -122,11 +122,6 @@
      * @param canvas  The picture is drawn to this canvas
      */
     public void draw(Canvas canvas) {
-        if (canvas.isHardwareAccelerated()) {
-            throw new IllegalArgumentException(
-                    "Picture playback is only supported on software canvas.");
-        }
-
         if (mRecordingCanvas != null) {
             endRecording();
         }
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 488ee4c..50a6df4 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -119,6 +119,23 @@
         a.recycle();
     }
 
+    private void setDrawable(Drawable dr) {
+        if (mDrawable != null) {
+            mDrawable.setCallback(null);
+        }
+
+        mDrawable = dr;
+
+        if (dr != null) {
+            dr.setCallback(this);
+            dr.setVisible(isVisible(), true);
+            dr.setState(getState());
+            dr.setLevel(getLevel());
+            dr.setBounds(getBounds());
+            dr.setLayoutDirection(getLayoutDirection());
+        }
+    }
+
     private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
             Theme theme) throws XmlPullParserException, IOException {
         // Load inner XML elements.
@@ -133,9 +150,10 @@
             }
 
             final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
-            mState.mDrawableState = dr.getConstantState();
-            mDrawable = dr;
-            dr.setCallback(this);
+            if (dr != null) {
+                mState.mDrawableState = dr.getConstantState();
+                setDrawable(dr);
+            }
         }
     }
 
@@ -166,8 +184,7 @@
                     final Drawable dr = a.getDrawable(attr);
                     if (dr != null) {
                         mState.mDrawableState = dr.getConstantState();
-                        mDrawable = dr;
-                        dr.setCallback(this);
+                        setDrawable(dr);
                     }
                     break;
                 case R.styleable.InsetDrawable_inset:
@@ -408,6 +425,7 @@
         if (!mMutated && super.mutate() == this) {
             mState = new InsetState(mState);
             mDrawable.mutate();
+            mState.mDrawableState = mDrawable.getConstantState();
             mMutated = true;
         }
         return this;
@@ -509,7 +527,8 @@
      */
     private void updateLocalState(Resources res) {
         if (mState.mDrawableState != null) {
-            mDrawable = mState.mDrawableState.newDrawable(res);
+            final Drawable dr = mState.mDrawableState.newDrawable(res);
+            setDrawable(dr);
         }
     }
 }
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index daf4427..505bd1d 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -29,6 +29,8 @@
 import android.graphics.PorterDuff.Mode;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.LayoutDirection;
+import android.view.Gravity;
 import android.view.View;
 
 import com.android.internal.R;
@@ -54,6 +56,11 @@
  * @attr ref android.R.styleable#LayerDrawableItem_top
  * @attr ref android.R.styleable#LayerDrawableItem_right
  * @attr ref android.R.styleable#LayerDrawableItem_bottom
+ * @attr ref android.R.styleable#LayerDrawableItem_start
+ * @attr ref android.R.styleable#LayerDrawableItem_end
+ * @attr ref android.R.styleable#LayerDrawableItem_width
+ * @attr ref android.R.styleable#LayerDrawableItem_height
+ * @attr ref android.R.styleable#LayerDrawableItem_gravity
  * @attr ref android.R.styleable#LayerDrawableItem_drawable
  * @attr ref android.R.styleable#LayerDrawableItem_id
 */
@@ -73,6 +80,9 @@
      */
     public static final int PADDING_MODE_STACK = 1;
 
+    /** Value used for undefined start and end insets. */
+    private static final int UNDEFINED_INSET = Integer.MIN_VALUE;
+
     LayerState mLayerState;
 
     private int mOpacityOverride = PixelFormat.UNKNOWN;
@@ -231,6 +241,16 @@
                 R.styleable.LayerDrawableItem_right, layer.mInsetR);
         layer.mInsetB = a.getDimensionPixelOffset(
                 R.styleable.LayerDrawableItem_bottom, layer.mInsetB);
+        layer.mInsetS = a.getDimensionPixelOffset(
+                R.styleable.LayerDrawableItem_start, layer.mInsetS);
+        layer.mInsetE = a.getDimensionPixelOffset(
+                R.styleable.LayerDrawableItem_end, layer.mInsetE);
+        layer.mWidth = a.getDimensionPixelSize(
+                R.styleable.LayerDrawableItem_width, layer.mWidth);
+        layer.mHeight = a.getDimensionPixelSize(
+                R.styleable.LayerDrawableItem_height, layer.mHeight);
+        layer.mGravity = a.getInteger(
+                R.styleable.LayerDrawableItem_gravity, layer.mGravity);
         layer.mId = a.getResourceId(R.styleable.LayerDrawableItem_id, layer.mId);
 
         final Drawable dr = a.getDrawable(R.styleable.LayerDrawableItem_drawable);
@@ -447,6 +467,89 @@
     }
 
     /**
+     * Sets an explicit size for the specified layer.
+     * <p>
+     * <strong>Note:</strong> Setting an explicit layer size changes the
+     * default layer gravity behavior. See {@link #setLayerGravity(int, int)}
+     * for more information.
+     *
+     * @param index the index of the drawable to adjust
+     * @param w width in pixels, or -1 to use the intrinsic width
+     * @param h height in pixels, or -1 to use the intrinsic height
+     *
+     * @see #getLayerWidth(int)
+     * @see #getLayerHeight(int)
+     * @attr ref android.R.styleable#LayerDrawableItem_width
+     * @attr ref android.R.styleable#LayerDrawableItem_height
+     */
+    public void setLayerSize(int index, int w, int h) {
+        final ChildDrawable childDrawable = mLayerState.mChildren[index];
+        childDrawable.mWidth = w;
+        childDrawable.mHeight = h;
+    }
+
+    /**
+     * @param index the index of the drawable to adjust
+     * @return the explicit width of the layer, or -1 if not specified
+     *
+     * @see #setLayerSize(int, int, int)
+     * @attr ref android.R.styleable#LayerDrawableItem_width
+     */
+    public int getLayerWidth(int index) {
+        final ChildDrawable childDrawable = mLayerState.mChildren[index];
+        return childDrawable.mWidth;
+    }
+
+    /**
+     * @param index the index of the drawable to adjust
+     * @return the explicit height of the layer, or -1 if not specified
+     *
+     * @see #setLayerSize(int, int, int)
+     * @attr ref android.R.styleable#LayerDrawableItem_height
+     */
+    public int getLayerHeight(int index) {
+        final ChildDrawable childDrawable = mLayerState.mChildren[index];
+        return childDrawable.mHeight;
+    }
+
+    /**
+     * Sets the gravity used to position or stretch the specified layer within
+     * its container. Gravity is applied after any layer insets (see
+     * {@link #setLayerInset(int, int, int, int, int)}) or padding (see
+     * {@link #setPaddingMode(int)}).
+     * <p>
+     * If gravity is specified as {@link Gravity#NO_GRAVITY}, the default
+     * behavior depends on whether an explicit width or height has been set
+     * (see {@link #setLayerSize(int, int, int)}), If a dimension is not set,
+     * gravity in that direction defaults to {@link Gravity#FILL_HORIZONTAL} or
+     * {@link Gravity#FILL_VERTICAL}; otherwise, gravity in that direction
+     * defaults to {@link Gravity#LEFT} or {@link Gravity#TOP}.
+     *
+     * @param index the index of the drawable to adjust
+     * @param gravity the gravity to set for the layer
+     *
+     * @see #getLayerGravity(int)
+     * @attr ref android.R.styleable#LayerDrawableItem_gravity
+     */
+    public void setLayerGravity(int index, int gravity) {
+        final ChildDrawable childDrawable = mLayerState.mChildren[index];
+        childDrawable.mGravity = gravity;
+    }
+
+    /**
+     * @param index the index of the layer
+     * @return the gravity used to position or stretch the specified layer
+     *         within its container
+     *
+     * @see #setLayerGravity(int, int)
+     * @attr ref android.R.styleable#LayerDrawableItem_gravity
+     */
+    public int getLayerGravity(int index) {
+        final ChildDrawable childDrawable = mLayerState.mChildren[index];
+        return childDrawable.mGravity;
+    }
+
+    /**
      * Specifies the insets in pixels for the drawable at the specified index.
      *
      * @param index the index of the drawable to adjust
@@ -454,13 +557,43 @@
      * @param t number of pixels to add to the top bound
      * @param r number of pixels to subtract from the right bound
      * @param b number of pixels to subtract from the bottom bound
+     *
+     * @attr ref android.R.styleable#LayerDrawableItem_left
+     * @attr ref android.R.styleable#LayerDrawableItem_top
+     * @attr ref android.R.styleable#LayerDrawableItem_right
+     * @attr ref android.R.styleable#LayerDrawableItem_bottom
      */
     public void setLayerInset(int index, int l, int t, int r, int b) {
+        setLayerInsetInternal(index, l, t, r, b, UNDEFINED_INSET, UNDEFINED_INSET);
+    }
+
+    /**
+     * Specifies the relative insets in pixels for the drawable at the
+     * specified index.
+     *
+     * @param index the index of the drawable to adjust
+     * @param s number of pixels to inset from the start bound
+     * @param t number of pixels to inset from the top bound
+     * @param e number of pixels to inset from the end bound
+     * @param b number of pixels to inset from the bottom bound
+     *
+     * @attr ref android.R.styleable#LayerDrawableItem_start
+     * @attr ref android.R.styleable#LayerDrawableItem_top
+     * @attr ref android.R.styleable#LayerDrawableItem_end
+     * @attr ref android.R.styleable#LayerDrawableItem_bottom
+     */
+    public void setLayerInsetRelative(int index, int s, int t, int e, int b) {
+        setLayerInsetInternal(index, 0, t, 0, b, s, e);
+    }
+
+    private void setLayerInsetInternal(int index, int l, int t, int r, int b, int s, int e) {
         final ChildDrawable childDrawable = mLayerState.mChildren[index];
         childDrawable.mInsetL = l;
         childDrawable.mInsetT = t;
         childDrawable.mInsetR = r;
         childDrawable.mInsetB = b;
+        childDrawable.mInsetS = s;
+        childDrawable.mInsetE = e;
     }
 
     /**
@@ -770,7 +903,7 @@
         }
 
         if (paddingChanged) {
-            onBoundsChange(getBounds());
+            updateLayerBounds(getBounds());
         }
 
         return changed;
@@ -795,7 +928,7 @@
         }
 
         if (paddingChanged) {
-            onBoundsChange(getBounds());
+            updateLayerBounds(getBounds());
         }
 
         return changed;
@@ -803,18 +936,50 @@
 
     @Override
     protected void onBoundsChange(Rect bounds) {
+        updateLayerBounds(bounds);
+    }
+
+    private void updateLayerBounds(Rect bounds) {
         int padL = 0;
         int padT = 0;
         int padR = 0;
         int padB = 0;
 
+        final Rect outRect = mTmpRect;
+        final int layoutDirection = getLayoutDirection();
         final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
         final ChildDrawable[] array = mLayerState.mChildren;
         final int N = mLayerState.mNum;
         for (int i = 0; i < N; i++) {
             final ChildDrawable r = array[i];
-            r.mDrawable.setBounds(bounds.left + r.mInsetL + padL, bounds.top + r.mInsetT + padT,
-                    bounds.right - r.mInsetR - padR, bounds.bottom - r.mInsetB - padB);
+            final Drawable d = r.mDrawable;
+            final Rect container = d.getBounds();
+
+            // Take the resolved layout direction into account. If start / end
+            // padding are defined, they will be resolved (hence overriding) to
+            // left / right or right / left depending on the resolved layout
+            // direction. If start / end padding are not defined, use the
+            // left / right ones.
+            final int insetL, insetR;
+            if (layoutDirection == LayoutDirection.RTL) {
+                insetL = r.mInsetE == UNDEFINED_INSET ? r.mInsetL : r.mInsetE;
+                insetR = r.mInsetS == UNDEFINED_INSET ? r.mInsetR : r.mInsetS;
+            } else {
+                insetL = r.mInsetS == UNDEFINED_INSET ? r.mInsetL : r.mInsetS;
+                insetR = r.mInsetE == UNDEFINED_INSET ? r.mInsetR : r.mInsetE;
+            }
+
+            // Establish containing region based on aggregate padding and
+            // requested insets for the current layer.
+            container.set(bounds.left + insetL + padL, bounds.top + r.mInsetT + padT,
+                    bounds.right - insetR - padR, bounds.bottom - r.mInsetB - padB);
+
+            // Apply resolved gravity to drawable based on resolved size.
+            final int gravity = resolveGravity(r.mGravity, r.mWidth, r.mHeight);
+            final int w = r.mWidth < 0 ? d.getIntrinsicWidth() : r.mWidth;
+            final int h = r.mHeight < 0 ? d.getIntrinsicHeight() : r.mHeight;
+            Gravity.apply(gravity, w, h, container, outRect, layoutDirection);
+            d.setBounds(outRect);
 
             if (nest) {
                 padL += mPaddingL[i];
@@ -825,6 +990,38 @@
         }
     }
 
+    /**
+     * Resolves layer gravity given explicit gravity and dimensions.
+     * <p>
+     * If the client hasn't specified a gravity but has specified an explicit
+     * dimension, defaults to START or TOP. Otherwise, defaults to FILL to
+     * preserve legacy behavior.
+     *
+     * @param gravity
+     * @param width
+     * @param height
+     * @return
+     */
+    private int resolveGravity(int gravity, int width, int height) {
+        if (!Gravity.isHorizontal(gravity)) {
+            if (width < 0) {
+                gravity |= Gravity.FILL_HORIZONTAL;
+            } else {
+                gravity |= Gravity.START;
+            }
+        }
+
+        if (!Gravity.isVertical(gravity)) {
+            if (height < 0) {
+                gravity |= Gravity.FILL_VERTICAL;
+            } else {
+                gravity |= Gravity.TOP;
+            }
+        }
+
+        return gravity;
+    }
+
     @Override
     public int getIntrinsicWidth() {
         int width = -1;
@@ -836,7 +1033,8 @@
         final int N = mLayerState.mNum;
         for (int i = 0; i < N; i++) {
             final ChildDrawable r = array[i];
-            final int w = r.mDrawable.getIntrinsicWidth() + r.mInsetL + r.mInsetR + padL + padR;
+            final int minWidth = r.mWidth < 0 ? r.mDrawable.getIntrinsicWidth() : r.mWidth;
+            final int w = minWidth + r.mInsetL + r.mInsetR + padL + padR;
             if (w > width) {
                 width = w;
             }
@@ -861,7 +1059,8 @@
         final int N = mLayerState.mNum;
         for (int i = 0; i < N; i++) {
             final ChildDrawable r = array[i];
-            int h = r.mDrawable.getIntrinsicHeight() + r.mInsetT + r.mInsetB + padT + padB;
+            final int minHeight = r.mHeight < 0 ? r.mDrawable.getIntrinsicHeight() : r.mHeight;
+            final int h = minHeight + r.mInsetT + r.mInsetB + padT + padB;
             if (h > height) {
                 height = h;
             }
@@ -948,18 +1147,24 @@
     /** @hide */
     @Override
     public void setLayoutDirection(int layoutDirection) {
+        super.setLayoutDirection(layoutDirection);
         final ChildDrawable[] array = mLayerState.mChildren;
         final int N = mLayerState.mNum;
         for (int i = 0; i < N; i++) {
             array[i].mDrawable.setLayoutDirection(layoutDirection);
         }
-        super.setLayoutDirection(layoutDirection);
+        updateLayerBounds(getBounds());
     }
 
     static class ChildDrawable {
         public Drawable mDrawable;
         public int[] mThemeAttrs;
         public int mInsetL, mInsetT, mInsetR, mInsetB;
+        public int mInsetS = UNDEFINED_INSET;
+        public int mInsetE = UNDEFINED_INSET;
+        public int mWidth = -1;
+        public int mHeight = -1;
+        public int mGravity = Gravity.NO_GRAVITY;
         public int mId = View.NO_ID;
 
         ChildDrawable() {
@@ -981,6 +1186,11 @@
             mInsetT = orig.mInsetT;
             mInsetR = orig.mInsetR;
             mInsetB = orig.mInsetB;
+            mInsetS = orig.mInsetS;
+            mInsetE = orig.mInsetE;
+            mWidth = orig.mWidth;
+            mHeight = orig.mHeight;
+            mGravity = orig.mGravity;
             mId = orig.mId;
         }
     }
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index 2e1364e..e05dd55 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -66,6 +66,7 @@
     ResourceCache.cpp \
     ShadowTessellator.cpp \
     SkiaCanvas.cpp \
+    SkiaCanvasProxy.cpp \
     SkiaShader.cpp \
     Snapshot.cpp \
     SpotShadow.cpp \
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index f9c8620..7ad0683 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -42,15 +42,15 @@
      */
     static Canvas* create_canvas(SkCanvas* skiaCanvas);
 
-    // TODO: enable HWUI to either create similar canvas wrapper or subclass
-    //       directly from Canvas
-    //static Canvas* create_canvas(uirenderer::Renderer* renderer);
-
-    // TODO: this is a temporary affordance until all necessary logic can be
-    //       moved within this interface! Further, the return value should
-    //       NOT be unref'd and is valid until this canvas is destroyed or a
-    //       new bitmap is set.
-    virtual SkCanvas* getSkCanvas() = 0;
+    /**
+     *  Provides a Skia SkCanvas interface that acts as a proxy to this Canvas.
+     *  It is useful for testing and clients (e.g. Picture/Movie) that expect to
+     *  draw their contents into an SkCanvas.
+     *
+     *  Further, the returned SkCanvas should NOT be unref'd and is valid until
+     *  this canvas is destroyed or a new bitmap is set.
+     */
+    virtual SkCanvas* asSkCanvas() = 0;
 
     virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0;
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d98d744..23181bc 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -59,6 +59,7 @@
     mPathMap.clear();
     DisplayListData* data = mDisplayListData;
     mDisplayListData = nullptr;
+    mSkiaCanvasProxy.reset(nullptr);
     return data;
 }
 
@@ -94,6 +95,15 @@
     mDisplayListData->functors.add(functor);
 }
 
+SkCanvas* DisplayListRenderer::asSkCanvas() {
+    LOG_ALWAYS_FATAL_IF(!mDisplayListData,
+            "attempting to get an SkCanvas when we are not recording!");
+    if (!mSkiaCanvasProxy) {
+        mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
+    }
+    return mSkiaCanvasProxy.get();
+}
+
 int DisplayListRenderer::save(SkCanvas::SaveFlags flags) {
     addStateOp(new (alloc()) SaveOp((int) flags));
     return mState.save((int) flags);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index d2b3ead..bd0b3b7 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -28,6 +28,7 @@
 #include "Canvas.h"
 #include "CanvasState.h"
 #include "DisplayList.h"
+#include "SkiaCanvasProxy.h"
 #include "RenderNode.h"
 #include "Renderer.h"
 #include "ResourceCache.h"
@@ -136,10 +137,8 @@
 // ----------------------------------------------------------------------------
 // android/graphics/Canvas interface
 // ----------------------------------------------------------------------------
-    virtual SkCanvas* getSkCanvas() override {
-        LOG_ALWAYS_FATAL("DisplayListRenderer has no SkCanvas");
-        return nullptr;
-    }
+    virtual SkCanvas* asSkCanvas() override;
+
     virtual void setBitmap(SkBitmap* bitmap, bool copyState) override {
         LOG_ALWAYS_FATAL("DisplayListRenderer is not backed by a bitmap.");
     }
@@ -244,6 +243,7 @@
 private:
 
     CanvasState mState;
+    std::unique_ptr<SkiaCanvasProxy> mSkiaCanvasProxy;
 
     enum DeferredBarrierType {
         kBarrier_None,
diff --git a/libs/hwui/Fence.h b/libs/hwui/Fence.h
deleted file mode 100644
index fc29f7ac1..0000000
--- a/libs/hwui/Fence.h
+++ /dev/null
@@ -1,113 +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.
- */
-
-#ifndef ANDROID_HWUI_FENCE_H
-#define ANDROID_HWUI_FENCE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-namespace android {
-namespace uirenderer {
-
-/**
- * Creating a Fence instance inserts a new sync fence in the OpenGL
- * commands stream. The caller can then wait for the fence to be signaled
- * by calling the wait method.
- */
-class Fence {
-public:
-    enum {
-        /**
-         * Default timeout in nano-seconds for wait()
-         */
-        kDefaultTimeout = 1000000000
-    };
-
-    /**
-     * Inserts a new sync fence in the OpenGL commands stream.
-     */
-    Fence() {
-        mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        if (mDisplay != EGL_NO_DISPLAY) {
-            mFence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, nullptr);
-        } else {
-            mFence = EGL_NO_SYNC_KHR;
-        }
-    }
-
-    /**
-     * Destroys the fence. Any caller waiting on the fence will be
-     * signaled immediately.
-     */
-    ~Fence() {
-        if (mFence != EGL_NO_SYNC_KHR) {
-            eglDestroySyncKHR(mDisplay, mFence);
-        }
-    }
-
-    /**
-     * Blocks the calling thread until this fence is signaled, or until
-     * <timeout> nanoseconds have passed.
-     *
-     * Returns true if waiting for the fence was successful, false if
-     * a timeout or an error occurred.
-     */
-    bool wait(EGLTimeKHR timeout = kDefaultTimeout) {
-        EGLint waitStatus = eglClientWaitSyncKHR(mDisplay, mFence,
-                EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, timeout);
-        if (waitStatus == EGL_FALSE) {
-            ALOGW("Failed to wait for the fence %#x", eglGetError());
-        }
-        return waitStatus == EGL_CONDITION_SATISFIED_KHR;
-    }
-
-private:
-    EGLDisplay mDisplay;
-    EGLSyncKHR mFence;
-
-}; // class Fence
-
-/**
- * An AutoFence creates a Fence instance and waits for the fence
- * to be signaled when the AutoFence is destroyed. This is useful
- * to automatically wait for a series of OpenGL commands to be
- * executed. For example:
- *
- * void drawAndWait() {
- *     glDrawElements();
- *     AutoFence fence;
- * }
- */
-class AutoFence {
-public:
-    AutoFence(EGLTimeKHR timeout = Fence::kDefaultTimeout): mTimeout(timeout) {
-    }
-
-    ~AutoFence() {
-        mFence.wait(mTimeout);
-    }
-
-private:
-    EGLTimeKHR mTimeout;
-    Fence mFence;
-
-}; // class AutoFence
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_FENCE_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index c4622f6..5a0cc1e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -18,7 +18,6 @@
 
 #include "DeferredDisplayList.h"
 #include "DisplayListRenderer.h"
-#include "Fence.h"
 #include "GammaFontRenderer.h"
 #include "Glop.h"
 #include "GlopBuilder.h"
@@ -504,7 +503,7 @@
     updateLayers();
     flushLayers();
     // Wait for all the layer updates to be executed
-    AutoFence fence;
+    glFinish();
 }
 
 void OpenGLRenderer::markLayersAsBuildLayers() {
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index d6eff85..e2caf8b 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -492,7 +492,9 @@
         if (mProcessor == nullptr) {
             mProcessor = new PathProcessor(Caches::getInstance());
         }
-        mProcessor->add(task);
+        if (!mProcessor->add(task)) {
+            mProcessor->process(task);
+        }
     }
 }
 
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 7fdbf9a..efbb709 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -46,82 +46,87 @@
         canvas->ref();
     }
 
-    virtual SkCanvas* getSkCanvas() {
+    virtual SkCanvas* asSkCanvas() override {
         return mCanvas.get();
     }
 
-    virtual void setBitmap(SkBitmap* bitmap, bool copyState);
+    virtual void setBitmap(SkBitmap* bitmap, bool copyState) override;
 
-    virtual bool isOpaque();
-    virtual int width();
-    virtual int height();
+    virtual bool isOpaque() override;
+    virtual int width() override;
+    virtual int height() override;
 
-    virtual int getSaveCount() const;
-    virtual int save(SkCanvas::SaveFlags flags);
-    virtual void restore();
-    virtual void restoreToCount(int saveCount);
+    virtual int getSaveCount() const override;
+    virtual int save(SkCanvas::SaveFlags flags) override;
+    virtual void restore() override;
+    virtual void restoreToCount(int saveCount) override;
 
     virtual int saveLayer(float left, float top, float right, float bottom,
-                const SkPaint* paint, SkCanvas::SaveFlags flags);
+                const SkPaint* paint, SkCanvas::SaveFlags flags) override;
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
-            int alpha, SkCanvas::SaveFlags flags);
+            int alpha, SkCanvas::SaveFlags flags) override;
 
-    virtual void getMatrix(SkMatrix* outMatrix) const;
-    virtual void setMatrix(const SkMatrix& matrix);
-    virtual void concat(const SkMatrix& matrix);
-    virtual void rotate(float degrees);
-    virtual void scale(float sx, float sy);
-    virtual void skew(float sx, float sy);
-    virtual void translate(float dx, float dy);
+    virtual void getMatrix(SkMatrix* outMatrix) const override;
+    virtual void setMatrix(const SkMatrix& matrix) override;
+    virtual void concat(const SkMatrix& matrix) override;
+    virtual void rotate(float degrees) override;
+    virtual void scale(float sx, float sy) override;
+    virtual void skew(float sx, float sy) override;
+    virtual void translate(float dx, float dy) override;
 
-    virtual bool getClipBounds(SkRect* outRect) const;
-    virtual bool quickRejectRect(float left, float top, float right, float bottom) const;
-    virtual bool quickRejectPath(const SkPath& path) const;
-    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
-    virtual bool clipPath(const SkPath* path, SkRegion::Op op);
-    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
+    virtual bool getClipBounds(SkRect* outRect) const override;
+    virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
+    virtual bool quickRejectPath(const SkPath& path) const override;
+    virtual bool clipRect(float left, float top, float right, float bottom,
+            SkRegion::Op op) override;
+    virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
+    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
 
-    virtual SkDrawFilter* getDrawFilter();
-    virtual void setDrawFilter(SkDrawFilter* drawFilter);
+    virtual SkDrawFilter* getDrawFilter() override;
+    virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
 
-    virtual void drawColor(int color, SkXfermode::Mode mode);
-    virtual void drawPaint(const SkPaint& paint);
+    virtual void drawColor(int color, SkXfermode::Mode mode) override;
+    virtual void drawPaint(const SkPaint& paint) override;
 
-    virtual void drawPoint(float x, float y, const SkPaint& paint);
-    virtual void drawPoints(const float* points, int count, const SkPaint& paint);
+    virtual void drawPoint(float x, float y, const SkPaint& paint) override;
+    virtual void drawPoints(const float* points, int count, const SkPaint& paint) override;
     virtual void drawLine(float startX, float startY, float stopX, float stopY,
-            const SkPaint& paint);
-    virtual void drawLines(const float* points, int count, const SkPaint& paint);
-    virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
+            const SkPaint& paint) override;
+    virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
+    virtual void drawRect(float left, float top, float right, float bottom,
+            const SkPaint& paint) override;
     virtual void drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, const SkPaint& paint);
-    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
-    virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
+            float rx, float ry, const SkPaint& paint) override;
+    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
+    virtual void drawOval(float left, float top, float right, float bottom,
+            const SkPaint& paint) override;
     virtual void drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint);
-    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
+    virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
     virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
             const float* verts, const float* tex, const int* colors,
-            const uint16_t* indices, int indexCount, const SkPaint& paint);
+            const uint16_t* indices, int indexCount, const SkPaint& paint) override;
 
-    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
-    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint);
+    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top,
+            const SkPaint* paint) override;
+    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+            const SkPaint* paint) override;
     virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, const SkPaint* paint);
+            float dstRight, float dstBottom, const SkPaint* paint) override;
     virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
-            const float* vertices, const int* colors, const SkPaint* paint);
+            const float* vertices, const int* colors, const SkPaint* paint) override;
 
     virtual void drawText(const uint16_t* text, const float* positions, int count,
             const SkPaint& paint, float x, float y,
             float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
-            float totalAdvance);
+            float totalAdvance) override;
     virtual void drawPosText(const uint16_t* text, const float* positions, int count,
-            int posCount, const SkPaint& paint);
+            int posCount, const SkPaint& paint) override;
     virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
-            float hOffset, float vOffset, const SkPaint& paint);
+            float hOffset, float vOffset, const SkPaint& paint) override;
 
-    virtual bool drawTextAbsolutePos() const { return true; }
+    virtual bool drawTextAbsolutePos() const  override { return true; }
 
 private:
     struct SaveRec {
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
new file mode 100644
index 0000000..de5f91c
--- /dev/null
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SkiaCanvasProxy.h"
+
+#include <cutils/log.h>
+#include <SkPatchUtils.h>
+
+namespace android {
+namespace uirenderer {
+
+SkiaCanvasProxy::SkiaCanvasProxy(Canvas* canvas)
+        : INHERITED(canvas->width(), canvas->height())
+        , mCanvas(canvas) {}
+
+void SkiaCanvasProxy::onDrawPaint(const SkPaint& paint) {
+    mCanvas->drawPaint(paint);
+}
+
+void SkiaCanvasProxy::onDrawPoints(PointMode pointMode, size_t count, const SkPoint pts[],
+        const SkPaint& paint) {
+    // convert the SkPoints into floats
+    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    const size_t floatCount = count << 1;
+    const float* floatArray = &pts[0].fX;
+
+    switch (pointMode) {
+        case kPoints_PointMode: {
+            mCanvas->drawPoints(floatArray, floatCount, paint);
+            break;
+        }
+        case kLines_PointMode: {
+            mCanvas->drawLines(floatArray, floatCount, paint);
+            break;
+        }
+        case kPolygon_PointMode: {
+            SkPaint strokedPaint(paint);
+            strokedPaint.setStyle(SkPaint::kStroke_Style);
+
+            SkPath path;
+            for (size_t i = 0; i < count - 1; i++) {
+                path.moveTo(pts[i]);
+                path.lineTo(pts[i+1]);
+                this->drawPath(path, strokedPaint);
+                path.rewind();
+            }
+            break;
+        }
+        default:
+            LOG_ALWAYS_FATAL("Unknown point type");
+    }
+}
+
+void SkiaCanvasProxy::onDrawOval(const SkRect& rect, const SkPaint& paint) {
+    mCanvas->drawOval(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint);
+}
+
+void SkiaCanvasProxy::onDrawRect(const SkRect& rect, const SkPaint& paint) {
+    mCanvas->drawRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint);
+}
+
+void SkiaCanvasProxy::onDrawRRect(const SkRRect& roundRect, const SkPaint& paint) {
+    if (!roundRect.isComplex()) {
+        const SkRect& rect = roundRect.rect();
+        SkVector radii = roundRect.getSimpleRadii();
+        mCanvas->drawRoundRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
+                               radii.fX, radii.fY, paint);
+    } else {
+        SkPath path;
+        path.addRRect(roundRect);
+        mCanvas->drawPath(path, paint);
+    }
+}
+
+void SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) {
+    mCanvas->drawPath(path, paint);
+}
+
+void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+        const SkPaint* paint) {
+    mCanvas->drawBitmap(bitmap, left, top, paint);
+}
+
+void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* srcPtr,
+        const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags) {
+    SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(bitmap.width(), bitmap.height());
+    mCanvas->drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
+                        dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+}
+
+void SkiaCanvasProxy::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+        const SkRect& dst, const SkPaint*) {
+    //TODO make nine-patch drawing a method on Canvas.h
+    SkDEBUGFAIL("SkiaCanvasProxy::onDrawBitmapNine is not yet supported");
+}
+
+void SkiaCanvasProxy::onDrawSprite(const SkBitmap& bitmap, int left, int top,
+        const SkPaint* paint) {
+    mCanvas->save(SkCanvas::kMatrixClip_SaveFlag);
+    mCanvas->setMatrix(SkMatrix::I());
+    mCanvas->drawBitmap(bitmap, left, top, paint);
+    mCanvas->restore();
+}
+
+void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[],
+        const SkPoint texs[], const SkColor colors[], SkXfermode*, const uint16_t indices[],
+        int indexCount, const SkPaint& paint) {
+    // convert the SkPoints into floats
+    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    const int floatCount = vertexCount << 1;
+    const float* vArray = &vertices[0].fX;
+    const float* tArray = (texs) ? &texs[0].fX : NULL;
+    const int* cArray = (colors) ? (int*)colors : NULL;
+    mCanvas->drawVertices(mode, floatCount, vArray, tArray, cArray, indices, indexCount, paint);
+}
+
+SkSurface* SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
+    SkDEBUGFAIL("SkiaCanvasProxy::onNewSurface is not supported");
+    return NULL;
+}
+
+void SkiaCanvasProxy::willSave() {
+    mCanvas->save(SkCanvas::kMatrixClip_SaveFlag);
+}
+
+SkCanvas::SaveLayerStrategy SkiaCanvasProxy::willSaveLayer(const SkRect* rectPtr,
+        const SkPaint* paint, SaveFlags flags) {
+    SkRect rect;
+    if (rectPtr) {
+        rect = *rectPtr;
+    } else if(!mCanvas->getClipBounds(&rect)) {
+        rect = SkRect::MakeEmpty();
+    }
+    mCanvas->saveLayer(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint, flags);
+    return SkCanvas::kNoLayer_SaveLayerStrategy;
+}
+
+void SkiaCanvasProxy::willRestore() {
+    mCanvas->restore();
+}
+
+void SkiaCanvasProxy::didConcat(const SkMatrix& matrix) {
+    mCanvas->concat(matrix);
+}
+
+void SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
+    mCanvas->setMatrix(matrix);
+}
+
+void SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+        const SkPaint& paint) {
+    SkPath path;
+    path.addRRect(outer);
+    path.addRRect(inner);
+    path.setFillType(SkPath::kEvenOdd_FillType);
+    this->drawPath(path, paint);
+}
+
+/**
+ * Utility class that converts the incoming text & paint from the given encoding
+ * into glyphIDs.
+ */
+class GlyphIDConverter {
+public:
+    GlyphIDConverter(const void* text, size_t byteLength, const SkPaint& origPaint) {
+        paint = origPaint;
+        if (paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding) {
+            glyphIDs = (uint16_t*)text;
+            count = byteLength >> 1;
+        } else {
+            storage.reset(byteLength); // ensures space for one glyph per ID given UTF8 encoding.
+            glyphIDs = storage.get();
+            count = paint.textToGlyphs(text, byteLength, storage.get());
+            paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        }
+    }
+
+    SkPaint paint;
+    uint16_t* glyphIDs;
+    int count;
+private:
+    SkAutoSTMalloc<32, uint16_t> storage;
+};
+
+void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+        const SkPaint& origPaint) {
+    // convert to glyphIDs if necessary
+    GlyphIDConverter glyphs(text, byteLength, origPaint);
+
+    // compute the glyph positions
+    SkAutoSTMalloc<32, SkPoint> pointStorage(glyphs.count);
+    SkAutoSTMalloc<32, SkScalar> glyphWidths(glyphs.count);
+    glyphs.paint.getTextWidths(glyphs.glyphIDs, glyphs.count << 1, glyphWidths.get());
+
+    // compute conservative bounds
+    // NOTE: We could call the faster paint.getFontBounds for a less accurate,
+    //       but even more conservative bounds if this  is too slow.
+    SkRect bounds;
+    glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
+
+    // adjust for non-left alignment
+    if (glyphs.paint.getTextAlign() != SkPaint::kLeft_Align) {
+        SkScalar stop = 0;
+        for (int i = 0; i < glyphs.count; i++) {
+            stop += glyphWidths[i];
+        }
+        if (glyphs.paint.getTextAlign() == SkPaint::kCenter_Align) {
+            stop = SkScalarHalf(stop);
+        }
+        if (glyphs.paint.isVerticalText()) {
+            y -= stop;
+        } else {
+            x -= stop;
+        }
+    }
+
+    // setup the first glyph position and adjust bounds if needed
+    if (mCanvas->drawTextAbsolutePos()) {
+        bounds.offset(x,y);
+        pointStorage[0].set(x, y);
+    } else {
+        pointStorage[0].set(0, 0);
+    }
+
+    // setup the remaining glyph positions
+    if (glyphs.paint.isVerticalText()) {
+        for (int i = 1; i < glyphs.count; i++) {
+            pointStorage[i].set(x, glyphWidths[i-1] + pointStorage[i-1].fY);
+        }
+    } else {
+        for (int i = 1; i < glyphs.count; i++) {
+            pointStorage[i].set(glyphWidths[i-1] + pointStorage[i-1].fX, y);
+        }
+    }
+
+    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    mCanvas->drawText(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
+                      x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
+}
+
+void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+        const SkPaint& origPaint) {
+    // convert to glyphIDs if necessary
+    GlyphIDConverter glyphs(text, byteLength, origPaint);
+
+    // convert to relative positions if necessary
+    int x, y;
+    const SkPoint* posArray;
+    SkAutoSTMalloc<32, SkPoint> pointStorage;
+    if (mCanvas->drawTextAbsolutePos()) {
+        x = 0;
+        y = 0;
+        posArray = pos;
+    } else {
+        x = pos[0].fX;
+        y = pos[0].fY;
+        posArray = pointStorage.reset(glyphs.count);
+        for (int i = 0; i < glyphs.count; i++) {
+            pointStorage[i].fX = pos[i].fX- x;
+            pointStorage[i].fY = pos[i].fY- y;
+        }
+    }
+
+    // compute conservative bounds
+    // NOTE: We could call the faster paint.getFontBounds for a less accurate,
+    //       but even more conservative bounds if this  is too slow.
+    SkRect bounds;
+    glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
+
+    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
+                      bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
+}
+
+void SkiaCanvasProxy::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+        SkScalar constY, const SkPaint& paint) {
+    const size_t pointCount = byteLength >> 1;
+    SkAutoSTMalloc<32, SkPoint> storage(pointCount);
+    SkPoint* pts = storage.get();
+    for (size_t i = 0; i < pointCount; i++) {
+        pts[i].set(xpos[i], constY);
+    }
+    this->onDrawPosText(text, byteLength, pts, paint);
+}
+
+void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+        const SkMatrix* matrix, const SkPaint& origPaint) {
+    // convert to glyphIDs if necessary
+    GlyphIDConverter glyphs(text, byteLength, origPaint);
+    mCanvas->drawTextOnPath(glyphs.glyphIDs, glyphs.count, path, 0, 0, glyphs.paint);
+}
+
+void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+        const SkPaint& paint) {
+    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextBlob is not supported");
+}
+
+void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+        const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+    SkPatchUtils::VertexData data;
+
+    SkMatrix matrix;
+    mCanvas->getMatrix(&matrix);
+    SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
+
+    // It automatically adjusts lodX and lodY in case it exceeds the number of indices.
+    // If it fails to generate the vertices, then we do not draw.
+    if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
+        this->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
+                           data.fTexCoords, data.fColors, xmode, data.fIndices, data.fIndexCount,
+                           paint);
+    }
+}
+
+void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) {
+    mCanvas->clipRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, op);
+}
+
+void SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkRegion::Op op, ClipEdgeStyle) {
+    SkPath path;
+    path.addRRect(roundRect);
+    mCanvas->clipPath(&path, op);
+}
+
+void SkiaCanvasProxy::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) {
+    mCanvas->clipPath(&path, op);
+}
+
+void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkRegion::Op op) {
+    mCanvas->clipRegion(&region, op);
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
new file mode 100644
index 0000000..4322fcf
--- /dev/null
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkiaCanvasProxy_DEFINED
+#define SkiaCanvasProxy_DEFINED
+
+#include <cutils/compiler.h>
+#include <SkCanvas.h>
+
+#include "Canvas.h"
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * This class serves as a proxy between Skia's SkCanvas and Android Framework's
+ * Canvas.  The class does not maintain any state and will pass through any request
+ * directly to the Canvas provided in the constructor.
+ *
+ * Upon construction it is expected that the provided Canvas has already been
+ * prepared for recording and will continue to be in the recording state while
+ * this proxy class is being used.
+ */
+class ANDROID_API SkiaCanvasProxy : public SkCanvas {
+public:
+    SkiaCanvasProxy(Canvas* canvas);
+    virtual ~SkiaCanvasProxy() {}
+
+protected:
+
+    virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
+
+    virtual void willSave() override;
+    virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) override;
+    virtual void willRestore() override;
+
+    virtual void didConcat(const SkMatrix&) override;
+    virtual void didSetMatrix(const SkMatrix&) override;
+
+    virtual void onDrawPaint(const SkPaint& paint) override;
+    virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[],
+                              const SkPaint&) override;
+    virtual void onDrawOval(const SkRect&, const SkPaint&) override;
+    virtual void onDrawRect(const SkRect&, const SkPaint&) override;
+    virtual void onDrawRRect(const SkRRect&, const SkPaint&) override;
+    virtual void onDrawPath(const SkPath& path, const SkPaint&) override;
+    virtual void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
+                              const SkPaint*) override;
+    virtual void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst,
+                                  const SkPaint* paint, DrawBitmapRectFlags flags) override;
+    virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+                                  const SkRect& dst, const SkPaint*) override;
+    virtual void onDrawSprite(const SkBitmap&, int left, int top,
+                              const SkPaint*) override;
+    virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
+                                const SkPoint texs[], const SkColor colors[], SkXfermode*,
+                                const uint16_t indices[], int indexCount,
+                                const SkPaint&) override;
+
+    virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
+
+    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+                            const SkPaint&) override;
+    virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+                               const SkPaint&) override;
+    virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+                                SkScalar constY, const SkPaint&) override;
+    virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+                                  const SkMatrix* matrix, const SkPaint&) override;
+    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+                                const SkPaint& paint) override;
+
+    virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+                             const SkPoint texCoords[4], SkXfermode* xmode,
+                             const SkPaint& paint) override;
+
+    virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
+    virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
+    virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
+    virtual void onClipRegion(const SkRegion&, SkRegion::Op) override;
+
+private:
+    Canvas* mCanvas;
+
+    typedef SkCanvas INHERITED;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // SkiaCanvasProxy_DEFINED
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 4f028d5..66de333 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -385,7 +385,9 @@
     if (mShadowProcessor == nullptr) {
         mShadowProcessor = new ShadowProcessor(Caches::getInstance());
     }
-    mShadowProcessor->add(task);
+    if (!mShadowProcessor->add(task)) {
+        mShadowProcessor->process(task);
+    }
 
     task->incStrong(nullptr); // not using sp<>s, so manually ref while in the cache
     mShadowCache.put(key, task.get());
@@ -421,7 +423,9 @@
         if (mProcessor == nullptr) {
             mProcessor = new TessellationProcessor(Caches::getInstance());
         }
-        mProcessor->add(task);
+        if (!mProcessor->add(task)) {
+            mProcessor->process(task);
+        }
         mCache.put(entry, buffer);
     }
     return buffer;
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index a819d9a..ba49833 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -44,7 +44,9 @@
     mStencil = new Stencil();
 
     // This is delayed because the first access of Caches makes GL calls
-    mCaches = &Caches::createInstance(*this);
+    if (!mCaches) {
+        mCaches = &Caches::createInstance(*this);
+    }
     mCaches->init();
     mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
 }
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index f2337cb..3afca2f 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -22,10 +22,13 @@
 
 #include <cutils/log.h>
 #include <cutils/properties.h>
+#include <EGL/eglext.h>
 
 #define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
 #define GLES_VERSION 2
 
+#define WAIT_FOR_GPU_COMPLETION 0
+
 // Android-specific addition that is used to show when frames began in systrace
 EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
 
@@ -260,6 +263,14 @@
 
 bool EglManager::swapBuffers(EGLSurface surface) {
     mInFrame = false;
+
+#if WAIT_FOR_GPU_COMPLETION
+    {
+        ATRACE_NAME("Finishing GPU work");
+        fence();
+    }
+#endif
+
     eglSwapBuffers(mEglDisplay, surface);
     EGLint err = eglGetError();
     if (CC_LIKELY(err == EGL_SUCCESS)) {
@@ -278,6 +289,13 @@
     return false;
 }
 
+void EglManager::fence() {
+    EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL);
+    eglClientWaitSyncKHR(mEglDisplay, fence,
+            EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
+    eglDestroySyncKHR(mEglDisplay, fence);
+}
+
 void EglManager::cancelFrame() {
     mInFrame = false;
 }
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index e12db3a..b1a18a9 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -55,6 +55,8 @@
 
     void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
 
+    void fence();
+
 private:
     friend class RenderThread;
 
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index 3c30aab..c69b2fd 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -105,6 +105,8 @@
 bool TaskManager::WorkerThread::addTask(TaskWrapper task) {
     if (!isRunning()) {
         run(mName.string(), PRIORITY_DEFAULT);
+    } else if (exitPending()) {
+        return false;
     }
 
     Mutex::Autolock l(mLock);
@@ -120,10 +122,6 @@
 }
 
 void TaskManager::WorkerThread::exit() {
-    {
-        Mutex::Autolock l(mLock);
-        mTasks.clear();
-    }
     requestExit();
     mSignal.signal();
 }
diff --git a/libs/hwui/thread/TaskProcessor.h b/libs/hwui/thread/TaskProcessor.h
index eb4ab64..ec6519c 100644
--- a/libs/hwui/thread/TaskProcessor.h
+++ b/libs/hwui/thread/TaskProcessor.h
@@ -30,9 +30,6 @@
     TaskProcessorBase() { }
     virtual ~TaskProcessorBase() { };
 
-private:
-    friend class TaskManager;
-
     virtual void process(const sp<TaskBase>& task) = 0;
 };
 
@@ -44,9 +41,6 @@
 
     bool add(const sp<Task<T> >& task);
 
-    virtual void onProcess(const sp<Task<T> >& task) = 0;
-
-private:
     virtual void process(const sp<TaskBase>& task) override {
         sp<Task<T> > realTask = static_cast<Task<T>* >(task.get());
         // This is the right way to do it but sp<> doesn't play nice
@@ -54,6 +48,8 @@
         onProcess(realTask);
     }
 
+    virtual void onProcess(const sp<Task<T> >& task) = 0;
+
     TaskManager* mManager;
 };
 
diff --git a/location/java/android/location/GpsSatellite.java b/location/java/android/location/GpsSatellite.java
index 17af4a6..820f5746 100644
--- a/location/java/android/location/GpsSatellite.java
+++ b/location/java/android/location/GpsSatellite.java
@@ -40,13 +40,17 @@
      * cached GpsStatus instance to the client's copy.
      */
     void setStatus(GpsSatellite satellite) {
-        mValid = satellite.mValid;
-        mHasEphemeris = satellite.mHasEphemeris;
-        mHasAlmanac = satellite.mHasAlmanac;
-        mUsedInFix = satellite.mUsedInFix;
-        mSnr = satellite.mSnr;
-        mElevation = satellite.mElevation;
-        mAzimuth = satellite.mAzimuth;
+        if (satellite == null) {
+            mValid = false;
+        } else {
+            mValid = satellite.mValid;
+            mHasEphemeris = satellite.mHasEphemeris;
+            mHasAlmanac = satellite.mHasAlmanac;
+            mUsedInFix = satellite.mUsedInFix;
+            mSnr = satellite.mSnr;
+            mElevation = satellite.mElevation;
+            mAzimuth = satellite.mAzimuth;
+        }
     }
 
     /**
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 4af55a6..323f326 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -16,6 +16,8 @@
 
 package android.location;
 
+import android.util.SparseArray;
+
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
@@ -29,20 +31,24 @@
 
     /* These package private values are modified by the LocationManager class */
     private int mTimeToFirstFix;
-    private GpsSatellite mSatellites[] = new GpsSatellite[NUM_SATELLITES];
+    private final SparseArray<GpsSatellite> mSatellites = new SparseArray<>();
 
     private final class SatelliteIterator implements Iterator<GpsSatellite> {
 
-        private GpsSatellite[] mSatellites;
-        int mIndex = 0;
+        private final SparseArray<GpsSatellite> mSatellites;
+        private final int mSatellitesCount;
 
-        SatelliteIterator(GpsSatellite[] satellites) {
+        private int mIndex = 0;
+
+        SatelliteIterator(SparseArray<GpsSatellite> satellites) {
             mSatellites = satellites;
+            mSatellitesCount = satellites.size();
         }
 
         public boolean hasNext() {
-            for (int i = mIndex; i < mSatellites.length; i++) {
-                if (mSatellites[i].mValid) {
+            for (; mIndex < mSatellitesCount; ++mIndex) {
+                GpsSatellite satellite = mSatellites.valueAt(mIndex);
+                if (satellite.mValid) {
                     return true;
                 }
             }
@@ -50,8 +56,9 @@
         }
 
         public GpsSatellite next() {
-            while (mIndex < mSatellites.length) {
-                GpsSatellite satellite = mSatellites[mIndex++];
+            while (mIndex < mSatellitesCount) {
+                GpsSatellite satellite = mSatellites.valueAt(mIndex);
+                ++mIndex;
                 if (satellite.mValid) {
                     return satellite;
                 }
@@ -106,7 +113,7 @@
          * <li> {@link GpsStatus#GPS_EVENT_SATELLITE_STATUS}
          * </ul>
          *
-         * When this method is called, the client should call 
+         * When this method is called, the client should call
          * {@link LocationManager#getGpsStatus} to get additional
          * status information.
          *
@@ -127,11 +134,8 @@
         void onNmeaReceived(long timestamp, String nmea);
     }
 
-    GpsStatus() {
-        for (int i = 0; i < mSatellites.length; i++) {
-            mSatellites[i] = new GpsSatellite(i + 1);
-        }
-    }
+    // For API-compat a public ctor() is not available
+    GpsStatus() {}
 
     /**
      * Used internally within {@link LocationManager} to copy GPS status
@@ -141,18 +145,17 @@
     synchronized void setStatus(int svCount, int[] prns, float[] snrs,
             float[] elevations, float[] azimuths, int ephemerisMask,
             int almanacMask, int usedInFixMask) {
-        int i;
+        clearSatellites();
+        for (int i = 0; i < svCount; i++) {
+            int prn = prns[i];
+            int prnShift = (1 << (prn - 1));
+            if (prn > 0 && prn <= NUM_SATELLITES) {
+                GpsSatellite satellite = mSatellites.get(prn);
+                if (satellite == null) {
+                    satellite = new GpsSatellite(prn);
+                    mSatellites.put(prn, satellite);
+                }
 
-        for (i = 0; i < mSatellites.length; i++) {
-            mSatellites[i].mValid = false;
-        }
-        
-        for (i = 0; i < svCount; i++) {
-            int prn = prns[i] - 1;
-            int prnShift = (1 << prn);
-            if (prn >= 0 && prn < mSatellites.length) {
-                GpsSatellite satellite = mSatellites[prn];
-    
                 satellite.mValid = true;
                 satellite.mSnr = snrs[i];
                 satellite.mElevation = elevations[i];
@@ -172,10 +175,38 @@
      */
     void setStatus(GpsStatus status) {
         mTimeToFirstFix = status.getTimeToFirstFix();
+        clearSatellites();
 
-        for (int i = 0; i < mSatellites.length; i++) {
-            mSatellites[i].setStatus(status.mSatellites[i]);
-        } 
+        SparseArray<GpsSatellite> otherSatellites = status.mSatellites;
+        int otherSatellitesCount = otherSatellites.size();
+        int satelliteIndex = 0;
+        // merge both sparse arrays, note that we have already invalidated the elements in the
+        // receiver array
+        for (int i = 0; i < otherSatellitesCount; ++i) {
+            GpsSatellite otherSatellite = otherSatellites.valueAt(i);
+            int otherSatellitePrn = otherSatellite.getPrn();
+
+            int satellitesCount = mSatellites.size();
+            while (satelliteIndex < satellitesCount
+                    && mSatellites.valueAt(satelliteIndex).getPrn() < otherSatellitePrn) {
+                ++satelliteIndex;
+            }
+
+            if (satelliteIndex < mSatellites.size()) {
+                GpsSatellite satellite = mSatellites.valueAt(satelliteIndex);
+                if (satellite.getPrn() == otherSatellitePrn) {
+                    satellite.setStatus(otherSatellite);
+                } else {
+                    satellite = new GpsSatellite(otherSatellitePrn);
+                    satellite.setStatus(otherSatellite);
+                    mSatellites.put(otherSatellitePrn, satellite);
+                }
+            } else {
+                GpsSatellite satellite = new GpsSatellite(otherSatellitePrn);
+                satellite.setStatus(otherSatellite);
+                mSatellites.append(otherSatellitePrn, satellite);
+            }
+        }
     }
 
     void setTimeToFirstFix(int ttff) {
@@ -183,7 +214,7 @@
     }
 
     /**
-     * Returns the time required to receive the first fix since the most recent 
+     * Returns the time required to receive the first fix since the most recent
      * restart of the GPS engine.
      *
      * @return time to first fix in milliseconds
@@ -211,4 +242,12 @@
     public int getMaxSatellites() {
         return NUM_SATELLITES;
     }
+
+    private void clearSatellites() {
+        int satellitesCount = mSatellites.size();
+        for (int i = 0; i < satellitesCount; i++) {
+            GpsSatellite satellite = mSatellites.valueAt(i);
+            satellite.mValid = false;
+        }
+    }
 }
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index fcf222b..bf3387b 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -170,6 +170,9 @@
      * Converts a coordinate to a String representation. The outputType
      * may be one of FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
      * The coordinate must be a valid double between -180.0 and 180.0.
+     * This conversion is performed in a method that is dependent on the
+     * default locale, and so is not guaranteed to round-trip with
+     * {@link #convert(String)}.
      *
      * @throws IllegalArgumentException if coordinate is less than
      * -180.0, greater than 180.0, or is not a number.
@@ -217,7 +220,9 @@
     /**
      * Converts a String in one of the formats described by
      * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS into a
-     * double.
+     * double. This conversion is performed in a locale agnostic
+     * method, and so is not guaranteed to round-trip with
+     * {@link #convert(double, int)}.
      *
      * @throws NullPointerException if coordinate is null
      * @throws IllegalArgumentException if the coordinate is not
diff --git a/location/tests/locationtests/src/android/location/GpsStatusTest.java b/location/tests/locationtests/src/android/location/GpsStatusTest.java
new file mode 100644
index 0000000..4808faf
--- /dev/null
+++ b/location/tests/locationtests/src/android/location/GpsStatusTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import junit.framework.TestCase;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link GpsStatus}.
+ */
+@SmallTest
+public class GpsStatusTest extends TestCase {
+
+    private static final int MAX_VALUE = 250;
+
+    private final Random mRandom = new Random();
+
+    private GpsStatus mStatus;
+    private int mCount;
+    private int[] mPrns;
+    private float[] mSnrs;
+    private float[] mElevations;
+    private float[] mAzimuth;
+    private int mEphemerisMask;
+    private int mAlmanacMask;
+    private int mUsedInFixMask;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        mStatus = createGpsStatus();
+        generateSatellitesData(generateInt());
+    }
+
+    public void testEmptyGpsStatus() throws Exception {
+        verifyIsEmpty(mStatus);
+    }
+
+    public void testGpsStatusIterator() throws Exception {
+        generateSatellitesData(2);
+        setSatellites(mStatus);
+        Iterator<GpsSatellite> iterator = mStatus.getSatellites().iterator();
+        assertTrue("hasNext(1)", iterator.hasNext());
+        assertTrue("hasNext(1) does not overflow", iterator.hasNext());
+        GpsSatellite satellite1 = iterator.next();
+        assertNotNull("satellite", satellite1);
+        assertTrue("hasNext(2)", iterator.hasNext());
+        assertTrue("hasNext(2) does not overflow", iterator.hasNext());
+        GpsSatellite satellite2 = iterator.next();
+        assertNotNull("satellite", satellite2);
+        assertFalse("hasNext() no elements", iterator.hasNext());
+    }
+
+    public void testTtff() throws Exception {
+        int testTtff = generateInt();
+        set(mStatus, testTtff);
+        verifyTtff(mStatus, testTtff);
+    }
+
+    public void testCopyTtff() throws Exception {
+        int testTtff = generateInt();
+        verifyTtff(mStatus, 0);
+
+        GpsStatus otherStatus = createGpsStatus();
+        set(otherStatus, testTtff);
+        verifyTtff(otherStatus, testTtff);
+
+        set(mStatus, otherStatus);
+        verifyTtff(mStatus, testTtff);
+    }
+
+    public void testSetSatellites() throws Exception {
+        setSatellites(mStatus);
+        verifySatellites(mStatus);
+    }
+
+    public void testCopySatellites() throws Exception {
+        verifyIsEmpty(mStatus);
+
+        GpsStatus otherStatus = createGpsStatus();
+        setSatellites(otherStatus);
+        verifySatellites(otherStatus);
+
+        set(mStatus, otherStatus);
+        verifySatellites(mStatus);
+    }
+
+    public void testOverrideSatellites() throws Exception {
+        setSatellites(mStatus);
+        verifySatellites(mStatus);
+
+        GpsStatus otherStatus = createGpsStatus();
+        generateSatellitesData(mCount, true /* reusePrns */);
+        setSatellites(otherStatus);
+        verifySatellites(otherStatus);
+
+        set(mStatus, otherStatus);
+        verifySatellites(mStatus);
+    }
+
+    public void testAddSatellites() throws Exception {
+        int count = 10;
+        generateSatellitesData(count);
+        setSatellites(mStatus);
+        verifySatellites(mStatus);
+
+        GpsStatus otherStatus = createGpsStatus();
+        generateSatellitesData(count);
+        setSatellites(otherStatus);
+        verifySatellites(otherStatus);
+
+        set(mStatus, otherStatus);
+        verifySatellites(mStatus);
+    }
+
+    public void testAddMoreSatellites() throws Exception {
+        int count = 25;
+        generateSatellitesData(count);
+        setSatellites(mStatus);
+        verifySatellites(mStatus);
+
+        GpsStatus otherStatus = createGpsStatus();
+        generateSatellitesData(count * 2);
+        setSatellites(otherStatus);
+        verifySatellites(otherStatus);
+
+        set(mStatus, otherStatus);
+        verifySatellites(mStatus);
+    }
+
+    public void testAddLessSatellites() throws Exception {
+        int count = 25;
+        generateSatellitesData(count * 2);
+        setSatellites(mStatus);
+        verifySatellites(mStatus);
+
+        GpsStatus otherStatus = createGpsStatus();
+        generateSatellitesData(count);
+        setSatellites(otherStatus);
+        verifySatellites(otherStatus);
+
+        set(mStatus, otherStatus);
+        verifySatellites(mStatus);
+    }
+
+    private static void verifyIsEmpty(GpsStatus status) {
+        verifySatelliteCount(status, 0);
+        verifyTtff(status, 0);
+    }
+
+    private static void verifySatelliteCount(GpsStatus status, int expectedCount) {
+        int satellites = 0;
+        for (GpsSatellite s : status.getSatellites()) {
+            ++satellites;
+        }
+        assertEquals("GpsStatus::SatelliteCount", expectedCount, satellites);
+    }
+
+    private void verifySatellites(GpsStatus status) {
+        verifySatelliteCount(status, mCount);
+        verifySatellites(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask,
+                mAlmanacMask, mUsedInFixMask);
+    }
+
+    private static void verifySatellites(
+            GpsStatus status,
+            int count,
+            int[] prns,
+            float[] snrs,
+            float[] elevations,
+            float[] azimuth,
+            int ephemerisMask,
+            int almanacMask,
+            int usedInFixMask) {
+        for (int i = 0; i < count; ++i) {
+            int prn = prns[i];
+            GpsSatellite satellite = getSatellite(status, prn);
+            assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite);
+            assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), snrs[i], satellite.getSnr());
+            assertEquals(
+                    getSatelliteAssertInfo(i, prn, "Elevation"),
+                    elevations[i],
+                    satellite.getElevation());
+            assertEquals(
+                    getSatelliteAssertInfo(i, prn, "Azimuth"),
+                    azimuth[i],
+                    satellite.getAzimuth());
+            int prnShift = 1 << (prn - 1);
+            assertEquals(
+                    getSatelliteAssertInfo(i, prn, "ephemeris"),
+                    (ephemerisMask & prnShift) != 0,
+                    satellite.hasEphemeris());
+            assertEquals(
+                    getSatelliteAssertInfo(i, prn, "almanac"),
+                    (almanacMask & prnShift) != 0,
+                    satellite.hasAlmanac());
+            assertEquals(
+                    getSatelliteAssertInfo(i, prn, "usedInFix"),
+                    (usedInFixMask & prnShift) != 0,
+                    satellite.usedInFix());
+        }
+    }
+
+    private static void verifyTtff(GpsStatus status, int expectedTtff) {
+        assertEquals("GpsStatus::TTFF", expectedTtff, status.getTimeToFirstFix());
+    }
+
+    private static GpsStatus createGpsStatus() throws Exception {
+        Constructor<GpsStatus>  ctor = GpsStatus.class.getDeclaredConstructor();
+        ctor.setAccessible(true);
+        return ctor.newInstance();
+    }
+
+    private static void set(GpsStatus status, int ttff) throws Exception {
+        Class<?> statusClass = status.getClass();
+        Method setTtff = statusClass.getDeclaredMethod("setTimeToFirstFix", Integer.TYPE);
+        setTtff.setAccessible(true);
+        setTtff.invoke(status, ttff);
+    }
+
+    private static void set(GpsStatus status, GpsStatus statusToSet) throws Exception {
+        Class<?> statusClass = status.getClass();
+        Method setStatus = statusClass.getDeclaredMethod("setStatus", statusClass);
+        setStatus.setAccessible(true);
+        setStatus.invoke(status, statusToSet);
+    }
+
+    private void setSatellites(GpsStatus status) throws Exception {
+        set(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
+                mUsedInFixMask);
+    }
+
+    private static void set(
+            GpsStatus status,
+            int count,
+            int[] prns,
+            float[] snrs,
+            float[] elevations,
+            float[] azimuth,
+            int ephemerisMask,
+            int almanacMask,
+            int usedInFixMask) throws Exception {
+        Class<?> statusClass = status.getClass();
+        Class<?> intClass = Integer.TYPE;
+        Class<?> floatArrayClass = Class.forName("[F");
+        Method setStatus = statusClass.getDeclaredMethod(
+                "setStatus",
+                intClass,
+                Class.forName("[I"),
+                floatArrayClass,
+                floatArrayClass,
+                floatArrayClass,
+                intClass,
+                intClass,
+                intClass);
+        setStatus.setAccessible(true);
+        setStatus.invoke(
+                status,
+                count,
+                prns,
+                snrs,
+                elevations,
+                azimuth,
+                ephemerisMask,
+                almanacMask,
+                usedInFixMask);
+    }
+
+    private int generateInt() {
+        return mRandom.nextInt(MAX_VALUE) + 1;
+    }
+
+    private int[] generateIntArray(int count) {
+        Set<Integer> generatedPrns = new HashSet<>();
+        int[] array = new int[count];
+        for(int i = 0; i < count; ++i) {
+            int generated;
+            do {
+                generated = generateInt();
+            } while (generatedPrns.contains(generated));
+            array[i] = generated;
+            generatedPrns.add(generated);
+        }
+        return array;
+    }
+
+    private float[] generateFloatArray(int count) {
+        float[] array = new float[count];
+        for(int i = 0; i < count; ++i) {
+            array[i] = generateInt();
+        }
+        return array;
+    }
+
+    private int generateMask(int[] prns) {
+        int mask = 0;
+        int prnsLength = prns.length;
+        for (int i = 0; i < prnsLength; ++i) {
+            if (mRandom.nextBoolean()) {
+                mask |= 1 << (prns[i] - 1);
+            }
+        }
+        return mask;
+    }
+
+    private void generateSatellitesData(int count) {
+        generateSatellitesData(count, false /* reusePrns */);
+    }
+
+    private void generateSatellitesData(int count, boolean reusePrns) {
+        mCount = count;
+        if (!reusePrns) {
+            mPrns = generateIntArray(count);
+        }
+        mSnrs = generateFloatArray(count);
+        mElevations = generateFloatArray(count);
+        mAzimuth = generateFloatArray(count);
+        mEphemerisMask = generateMask(mPrns);
+        mAlmanacMask = generateMask(mPrns);
+        mUsedInFixMask = generateMask(mPrns);
+    }
+
+    private static GpsSatellite getSatellite(GpsStatus status, int prn) {
+        for (GpsSatellite satellite : status.getSatellites()) {
+            if (satellite.getPrn() == prn) {
+                return satellite;
+            }
+        }
+        return null;
+    }
+
+    private static String getSatelliteAssertInfo(int index, int prn, String param) {
+        return String.format("Satellite::%s [i=%d, prn=%d]", param, index, prn);
+    }
+}
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 489f552..ca242e4 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -709,7 +709,13 @@
         }
     }
 
-    /** @hide */
+    /**
+     * @hide
+     * Only use to get which stream type should be used for volume control, NOT for audio playback
+     * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
+     * @param aa non-null AudioAttributes.
+     * @return a valid stream type for volume control that matches the attributes.
+     */
     public static int toLegacyStreamType(AudioAttributes aa) {
         // flags to stream type mapping
         if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index b10736b..82da27d 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -36,12 +36,13 @@
     private final int mType;
     private final String mAddress;
 
-    AudioDevicePort(AudioHandle handle, int[] samplingRates, int[] channelMasks,
+    AudioDevicePort(AudioHandle handle, String deviceName,
+            int[] samplingRates, int[] channelMasks,
             int[] formats, AudioGain[] gains, int type, String address) {
         super(handle,
              (AudioManager.isInputDevice(type) == true)  ?
                         AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK,
-             samplingRates, channelMasks, formats, gains);
+             deviceName, samplingRates, channelMasks, formats, gains);
         mType = type;
         mAddress = address;
     }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9bcf3c8..07b19a4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -46,9 +46,9 @@
 import android.util.Log;
 import android.view.KeyEvent;
 
-import java.util.HashMap;
 import java.util.ArrayList;
-
+import java.util.HashMap;
+import java.util.Iterator;
 
 /**
  * AudioManager provides access to volume and ringer mode control.
@@ -346,6 +346,31 @@
      */
     public static final int ADJUST_SAME = 0;
 
+    /**
+     * Mute the volume. Has no effect if the stream is already muted.
+     *
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int ADJUST_MUTE = -100;
+
+    /**
+     * Unmute the volume. Has no effect if the stream is not muted.
+     *
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int ADJUST_UNMUTE = 100;
+
+    /**
+     * Toggle the mute state. If muted the stream will be unmuted. If not muted
+     * the stream will be muted.
+     *
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int ADJUST_TOGGLE_MUTE = 101;
+
     // Flags should be powers of 2!
 
     /**
@@ -777,13 +802,17 @@
      * screen is showing. Another example, if music is playing in the background
      * and a call is not active, the music stream will be adjusted.
      * <p>
-     * This method should only be used by applications that replace the platform-wide
-     * management of audio settings or the main telephony application.
-     * <p>This method has no effect if the device implements a fixed volume policy
+     * This method should only be used by applications that replace the
+     * platform-wide management of audio settings or the main telephony
+     * application.
+     * <p>
+     * This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
+     *
      * @param direction The direction to adjust the volume. One of
-     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
-     *            {@link #ADJUST_SAME}.
+     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE},
+     *            {@link #ADJUST_SAME}, {@link #ADJUST_MUTE},
+     *            {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}.
      * @param flags One or more flags.
      * @see #adjustSuggestedStreamVolume(int, int, int)
      * @see #adjustStreamVolume(int, int, int)
@@ -808,16 +837,20 @@
      * Adjusts the volume of the most relevant stream, or the given fallback
      * stream.
      * <p>
-     * This method should only be used by applications that replace the platform-wide
-     * management of audio settings or the main telephony application.
-     *
-     * <p>This method has no effect if the device implements a fixed volume policy
+     * This method should only be used by applications that replace the
+     * platform-wide management of audio settings or the main telephony
+     * application.
+     * <p>
+     * This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
+     *
      * @param direction The direction to adjust the volume. One of
-     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
-     *            {@link #ADJUST_SAME}.
+     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE},
+     *            {@link #ADJUST_SAME}, {@link #ADJUST_MUTE},
+     *            {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}.
      * @param suggestedStreamType The stream type that will be used if there
-     *            isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is valid here.
+     *            isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is
+     *            valid here.
      * @param flags One or more flags.
      * @see #adjustVolume(int, int)
      * @see #adjustStreamVolume(int, int, int)
@@ -1088,77 +1121,81 @@
     }
 
     /**
-     * Solo or unsolo a particular stream. All other streams are muted.
+     * Solo or unsolo a particular stream.
      * <p>
-     * The solo command is protected against client process death: if a process
-     * with an active solo request on a stream dies, all streams that were muted
-     * because of this request will be unmuted automatically.
-     * <p>
-     * The solo requests for a given stream are cumulative: the AudioManager
-     * can receive several solo requests from one or more clients and the stream
-     * will be unsoloed only when the same number of unsolo requests are received.
-     * <p>
-     * For a better user experience, applications MUST unsolo a soloed stream
-     * in onPause() and solo is again in onResume() if appropriate.
-     * <p>This method has no effect if the device implements a fixed volume policy
-     * as indicated by {@link #isVolumeFixed()}.
+     * Do not use. This method has been deprecated and is now a no-op.
+     * {@link #requestAudioFocus} should be used for exclusive audio playback.
      *
      * @param streamType The stream to be soloed/unsoloed.
-     * @param state The required solo state: true for solo ON, false for solo OFF
-     *
+     * @param state The required solo state: true for solo ON, false for solo
+     *            OFF
      * @see #isVolumeFixed()
+     * @deprecated Do not use. If you need exclusive audio playback use
+     *             {@link #requestAudioFocus}.
      */
+    @Deprecated
     public void setStreamSolo(int streamType, boolean state) {
-        IAudioService service = getService();
-        try {
-            service.setStreamSolo(streamType, state, mICallBack);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setStreamSolo", e);
-        }
+        Log.w(TAG, "setStreamSolo has been deprecated. Do not use.");
     }
 
     /**
      * Mute or unmute an audio stream.
      * <p>
-     * The mute command is protected against client process death: if a process
-     * with an active mute request on a stream dies, this stream will be unmuted
-     * automatically.
+     * This method should only be used by applications that replace the
+     * platform-wide management of audio settings or the main telephony
+     * application.
      * <p>
-     * The mute requests for a given stream are cumulative: the AudioManager
-     * can receive several mute requests from one or more clients and the stream
-     * will be unmuted only when the same number of unmute requests are received.
-     * <p>
-     * For a better user experience, applications MUST unmute a muted stream
-     * in onPause() and mute is again in onResume() if appropriate.
-     * <p>
-     * This method should only be used by applications that replace the platform-wide
-     * management of audio settings or the main telephony application.
-     * <p>This method has no effect if the device implements a fixed volume policy
+     * This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
+     * <p>
+     * This method was deprecated in API level 22. Prior to API level 22 this
+     * method had significantly different behavior and should be used carefully.
+     * The following applies only to pre-22 platforms:
+     * <ul>
+     * <li>The mute command is protected against client process death: if a
+     * process with an active mute request on a stream dies, this stream will be
+     * unmuted automatically.</li>
+     * <li>The mute requests for a given stream are cumulative: the AudioManager
+     * can receive several mute requests from one or more clients and the stream
+     * will be unmuted only when the same number of unmute requests are
+     * received.</li>
+     * <li>For a better user experience, applications MUST unmute a muted stream
+     * in onPause() and mute is again in onResume() if appropriate.</li>
+     * </ul>
      *
      * @param streamType The stream to be muted/unmuted.
-     * @param state The required mute state: true for mute ON, false for mute OFF
-     *
+     * @param state The required mute state: true for mute ON, false for mute
+     *            OFF
      * @see #isVolumeFixed()
+     * @deprecated Use {@link #adjustStreamVolume(int, int, int)} with
+     *             {@link #ADJUST_MUTE} or {@link #ADJUST_UNMUTE} instead.
      */
+    @Deprecated
     public void setStreamMute(int streamType, boolean state) {
-        IAudioService service = getService();
-        try {
-            service.setStreamMute(streamType, state, mICallBack);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setStreamMute", e);
+        Log.w(TAG, "setStreamMute is deprecated. adjustStreamVolume should be used instead.");
+        int direction = state ? ADJUST_MUTE : ADJUST_UNMUTE;
+        if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+            adjustSuggestedStreamVolume(direction, streamType, 0);
+        } else {
+            adjustStreamVolume(streamType, direction, 0);
         }
     }
 
     /**
-     * get stream mute state.
+     * Returns the current mute state for a particular stream.
      *
-     * @hide
+     * @param streamType The stream to get mute state for.
+     * @return The mute state for the given stream.
+     * @see #adjustStreamVolume(int, int, int)
      */
     public boolean isStreamMute(int streamType) {
         IAudioService service = getService();
         try {
-            return service.isStreamMute(streamType);
+            if (mUseMasterVolume) {
+                return service.isMasterMute();
+            } else {
+                return service.isStreamMute(streamType);
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in isStreamMute", e);
             return false;
@@ -1166,29 +1203,6 @@
     }
 
     /**
-     * set master mute state.
-     *
-     * @hide
-     */
-    public void setMasterMute(boolean state) {
-        setMasterMute(state, FLAG_SHOW_UI);
-    }
-
-    /**
-     * set master mute state with optional flags.
-     *
-     * @hide
-     */
-    public void setMasterMute(boolean state, int flags) {
-        IAudioService service = getService();
-        try {
-            service.setMasterMute(state, flags, mContext.getOpPackageName(), mICallBack);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setMasterMute", e);
-        }
-    }
-
-    /**
      * get master mute state.
      *
      * @hide
@@ -3189,10 +3203,10 @@
      * @param name   device name
      * {@hide}
      */
-    public void setWiredDeviceConnectionState(int device, int state, String name) {
+    public void setWiredDeviceConnectionState(int type, int state, String address, String name) {
         IAudioService service = getService();
         try {
-            service.setWiredDeviceConnectionState(device, state, name);
+            service.setWiredDeviceConnectionState(type, state, address, name);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
         }
@@ -3588,11 +3602,13 @@
                     newPorts.clear();
                     status = AudioSystem.listAudioPorts(newPorts, portGeneration);
                     if (status != SUCCESS) {
+                        Log.w(TAG, "updateAudioPortCache: listAudioPorts failed");
                         return status;
                     }
                     newPatches.clear();
                     status = AudioSystem.listAudioPatches(newPatches, patchGeneration);
                     if (status != SUCCESS) {
+                        Log.w(TAG, "updateAudioPortCache: listAudioPatches failed");
                         return status;
                     }
                 } while (patchGeneration[0] != portGeneration[0]);
@@ -3601,20 +3617,35 @@
                     for (int j = 0; j < newPatches.get(i).sources().length; j++) {
                         AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j],
                                                                    newPorts);
-                        if (portCfg == null) {
-                            return ERROR;
-                        }
                         newPatches.get(i).sources()[j] = portCfg;
                     }
                     for (int j = 0; j < newPatches.get(i).sinks().length; j++) {
                         AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j],
                                                                    newPorts);
-                        if (portCfg == null) {
-                            return ERROR;
-                        }
                         newPatches.get(i).sinks()[j] = portCfg;
                     }
                 }
+                for (Iterator<AudioPatch> i = newPatches.iterator(); i.hasNext(); ) {
+                    AudioPatch newPatch = i.next();
+                    boolean hasInvalidPort = false;
+                    for (AudioPortConfig portCfg : newPatch.sources()) {
+                        if (portCfg == null) {
+                            hasInvalidPort = true;
+                            break;
+                        }
+                    }
+                    for (AudioPortConfig portCfg : newPatch.sinks()) {
+                        if (portCfg == null) {
+                            hasInvalidPort = true;
+                            break;
+                        }
+                    }
+                    if (hasInvalidPort) {
+                        // Temporarily remove patches with invalid ports. One who created the patch
+                        // is responsible for dealing with the port change.
+                        i.remove();
+                    }
+                }
 
                 sAudioPortsCached = newPorts;
                 sAudioPatchesCached = newPatches;
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index 616bdd1..873c142 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -41,9 +41,6 @@
     public abstract void adjustMasterVolumeForUid(int steps, int flags, String callingPackage,
             int uid);
 
-    public abstract void setMasterMuteForUid(boolean state, int flags, String callingPackage,
-            IBinder cb, int uid);
-
     public abstract void setRingerModeDelegate(RingerModeDelegate delegate);
 
     public abstract int getRingerModeInternal();
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index 1500a43..9fac8d1 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -26,9 +26,10 @@
 
 public class AudioMixPort extends AudioPort {
 
-    AudioMixPort(AudioHandle handle, int role, int[] samplingRates, int[] channelMasks,
+    AudioMixPort(AudioHandle handle, int role, String deviceName,
+            int[] samplingRates, int[] channelMasks,
             int[] formats, AudioGain[] gains) {
-        super(handle, role, samplingRates, channelMasks, formats, gains);
+        super(handle, role, deviceName, samplingRates, channelMasks, formats, gains);
     }
 
     /**
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 1ab7e89..b046791 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -15,7 +15,7 @@
  */
 
 package android.media;
-
+import android.util.Slog;
 
 /**
  * An audio port is a node of the audio framework or hardware that can be connected to or
@@ -37,6 +37,7 @@
  * @hide
  */
 public class AudioPort {
+    private static final String TAG = "AudioPort";
 
     /**
      * For use by the audio framework.
@@ -68,16 +69,20 @@
 
     AudioHandle mHandle;
     protected final int mRole;
+    private final String mName;
     private final int[] mSamplingRates;
     private final int[] mChannelMasks;
     private final int[] mFormats;
     private final AudioGain[] mGains;
     private AudioPortConfig mActiveConfig;
 
-    AudioPort(AudioHandle handle, int role, int[] samplingRates, int[] channelMasks,
+    AudioPort(AudioHandle handle, int role, String name,
+            int[] samplingRates, int[] channelMasks,
             int[] formats, AudioGain[] gains) {
+
         mHandle = handle;
         mRole = role;
+        mName = name;
         mSamplingRates = samplingRates;
         mChannelMasks = channelMasks;
         mFormats = formats;
@@ -96,6 +101,14 @@
     }
 
     /**
+     * Get the human-readable name of this port. Perhaps an internal
+     * designation or an physical device.
+     */
+    public String name() {
+        return mName;
+    }
+
+    /**
      * Get the list of supported sampling rates
      * Empty array if sampling rate is not relevant for this audio port
      */
diff --git a/media/java/android/media/AudioRoutesInfo.java b/media/java/android/media/AudioRoutesInfo.java
index df9fc06..3e0ec07 100644
--- a/media/java/android/media/AudioRoutesInfo.java
+++ b/media/java/android/media/AudioRoutesInfo.java
@@ -30,6 +30,7 @@
     static final int MAIN_HEADPHONES = 1<<1;
     static final int MAIN_DOCK_SPEAKERS = 1<<2;
     static final int MAIN_HDMI = 1<<3;
+    static final int MAIN_USB = 1<<4;
 
     CharSequence mBluetoothName;
     int mMainType = MAIN_SPEAKER;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0ffa5fc..3e91e4c 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -153,11 +153,11 @@
     private final AppOpsManager mAppOps;
 
     // the platform has no specific capabilities
-    private static final int PLATFORM_DEFAULT = 0;
+    public static final int PLATFORM_DEFAULT = 0;
     // the platform is voice call capable (a phone)
-    private static final int PLATFORM_VOICE = 1;
+    public static final int PLATFORM_VOICE = 1;
     // the platform is a television or a set-top box
-    private static final int PLATFORM_TELEVISION = 2;
+    public static final int PLATFORM_TELEVISION = 2;
     // the platform type affects volume and silent mode behavior
     private final int mPlatformType;
 
@@ -356,6 +356,12 @@
             "STREAM_TTS"
     };
 
+    public static final int DEFAULT_MUTE_STREAMS_AFFECTED =
+            (1 << AudioSystem.STREAM_MUSIC) |
+            (1 << AudioSystem.STREAM_RING) |
+            (1 << AudioSystem.STREAM_NOTIFICATION) |
+            (1 << AudioSystem.STREAM_SYSTEM);
+
     private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
         public void onError(int error) {
             switch (error) {
@@ -536,6 +542,20 @@
 
     private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
 
+    // Intent "extra" data keys.
+    public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName";
+    public static final String CONNECT_INTENT_KEY_STATE = "state";
+    public static final String CONNECT_INTENT_KEY_ADDRESS = "address";
+    public static final String CONNECT_INTENT_KEY_HAS_PLAYBACK = "hasPlayback";
+    public static final String CONNECT_INTENT_KEY_HAS_CAPTURE = "hasCapture";
+    public static final String CONNECT_INTENT_KEY_HAS_MIDI = "hasMIDI";
+    public static final String CONNECT_INTENT_KEY_DEVICE_CLASS = "class";
+
+    // Defines the format for the connection "address" for ALSA devices
+    public static String makeAlsaAddressString(int card, int device) {
+        return "card=" + card + ";device=" + device + ";";
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -546,15 +566,7 @@
         mContentResolver = context.getContentResolver();
         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
 
-        if (mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_voice_capable)) {
-            mPlatformType = PLATFORM_VOICE;
-        } else if (context.getPackageManager().hasSystemFeature(
-                                                            PackageManager.FEATURE_LEANBACK)) {
-            mPlatformType = PLATFORM_TELEVISION;
-        } else {
-            mPlatformType = PLATFORM_DEFAULT;
-        }
+        mPlatformType = getPlatformType(context);
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
@@ -667,6 +679,26 @@
         LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
     }
 
+    /**
+     * Return the platform type that this is running on. One of:
+     * <ul>
+     * <li>{@link #PLATFORM_VOICE}</li>
+     * <li>{@link #PLATFORM_TELEVISION}</li>
+     * <li>{@link #PLATFORM_DEFAULT}</li>
+     * </ul>
+     */
+    public static int getPlatformType(Context context) {
+        if (context.getResources().getBoolean(
+                com.android.internal.R.bool.config_voice_capable)) {
+            return PLATFORM_VOICE;
+        } else if (context.getPackageManager().hasSystemFeature(
+                                                            PackageManager.FEATURE_LEANBACK)) {
+            return PLATFORM_TELEVISION;
+        } else {
+            return PLATFORM_DEFAULT;
+        }
+    }
+
     public void systemReady() {
         sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
                 0, 0, null, 0);
@@ -748,7 +780,7 @@
                                     setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
                 }
                 // apply stream volume
-                if (!mStreamStates[streamType].isMuted_syncVSS()) {
+                if (!mStreamStates[streamType].mIsMuted) {
                     mStreamStates[streamType].applyAllVolumes();
                 }
             }
@@ -899,11 +931,8 @@
         }
 
         mMuteAffectedStreams = System.getIntForUser(cr,
-                System.MUTE_STREAMS_AFFECTED,
-                ((1 << AudioSystem.STREAM_MUSIC)|
-                 (1 << AudioSystem.STREAM_RING)|
-                 (1 << AudioSystem.STREAM_SYSTEM)),
-                 UserHandle.USER_CURRENT);
+                System.MUTE_STREAMS_AFFECTED, DEFAULT_MUTE_STREAMS_AFFECTED,
+                UserHandle.USER_CURRENT);
 
         boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
                                                   0, UserHandle.USER_CURRENT) == 1;
@@ -970,6 +999,7 @@
         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType
                 + ", flags=" + flags);
         int streamType;
+        boolean isMute = isMuteAdjust(direction);
         if (mVolumeControlStream != -1) {
             streamType = mVolumeControlStream;
         } else {
@@ -984,7 +1014,8 @@
         }
 
         // For notifications/ring, show the ui before making any adjustments
-        if (mVolumeController.suppressAdjustment(resolvedStream, flags)) {
+        // Don't suppress mute/unmute requests
+        if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
             direction = 0;
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
             flags &= ~AudioManager.FLAG_VIBRATE;
@@ -1011,10 +1042,17 @@
         ensureValidDirection(direction);
         ensureValidStreamType(streamType);
 
+        boolean isMuteAdjust = isMuteAdjust(direction);
+
         // use stream type alias here so that streams with same alias have the same behavior,
         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
         int streamTypeAlias = mStreamVolumeAlias[streamType];
+
+        if (isMuteAdjust && !isStreamAffectedByMute(streamTypeAlias)) {
+            return;
+        }
+
         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
 
         final int device = getDeviceForStream(streamTypeAlias);
@@ -1100,13 +1138,37 @@
                 }
             }
 
-            if ((direction == AudioManager.ADJUST_RAISE) &&
+            if (isMuteAdjust) {
+                boolean state;
+                if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
+                    state = !streamState.mIsMuted;
+                } else {
+                    state = direction == AudioManager.ADJUST_MUTE;
+                }
+                if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
+                    setSystemAudioMute(state);
+                }
+                for (int stream = 0; stream < mStreamStates.length; stream++) {
+                    if (streamTypeAlias == mStreamVolumeAlias[stream]) {
+                        mStreamStates[stream].mute(state);
+
+                        Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+                        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream);
+                        intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
+                        sendBroadcastToAll(intent);
+                    }
+                }
+            } else if ((direction == AudioManager.ADJUST_RAISE) &&
                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
-                Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
+                Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
                 mVolumeController.postDisplaySafeVolumeWarning(flags);
-            } else if (streamState.adjustIndex(direction * step, device)) {
-                // Post message to set system volume (it in turn will post a message
-                // to persist). Do not change volume if stream is muted.
+            } else if (streamState.adjustIndex(direction * step, device) || streamState.mIsMuted) {
+                // Post message to set system volume (it in turn will post a
+                // message to persist).
+                if (streamState.mIsMuted) {
+                    // Unmute the stream if it was previously muted
+                    streamState.mute(false);
+                }
                 sendMsg(mAudioHandler,
                         MSG_SET_DEVICE_VOLUME,
                         SENDMSG_QUEUE,
@@ -1116,7 +1178,7 @@
                         0);
             }
 
-            // Check if volume update should be send to Hdmi system audio.
+            // Check if volume update should be sent to Hdmi system audio.
             int newIndex = mStreamStates[streamType].getIndex(device);
             if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
@@ -1129,7 +1191,7 @@
                             oldIndex != newIndex) {
                         synchronized (mHdmiPlaybackClient) {
                             int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
-                                                               KeyEvent.KEYCODE_VOLUME_UP;
+                                    KeyEvent.KEYCODE_VOLUME_UP;
                             mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
                             mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
                         }
@@ -1172,6 +1234,10 @@
         if (mUseFixedVolume) {
             return;
         }
+        if (isMuteAdjust(steps)) {
+            setMasterMuteInternal(steps, flags, callingPackage, uid);
+            return;
+        }
         ensureValidSteps(steps);
         int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
         int delta = 0;
@@ -1500,46 +1566,6 @@
         }
     }
 
-    /** @see AudioManager#setStreamSolo(int, boolean) */
-    public void setStreamSolo(int streamType, boolean state, IBinder cb) {
-        if (mUseFixedVolume) {
-            return;
-        }
-        int streamAlias = mStreamVolumeAlias[streamType];
-        for (int stream = 0; stream < mStreamStates.length; stream++) {
-            if (!isStreamAffectedByMute(streamAlias) || streamAlias == mStreamVolumeAlias[stream]) {
-                continue;
-            }
-            mStreamStates[stream].mute(cb, state);
-         }
-    }
-
-    /** @see AudioManager#setStreamMute(int, boolean) */
-    public void setStreamMute(int streamType, boolean state, IBinder cb) {
-        if (mUseFixedVolume) {
-            return;
-        }
-        if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-            streamType = getActiveStreamType(streamType);
-        }
-        int streamAlias = mStreamVolumeAlias[streamType];
-        if (isStreamAffectedByMute(streamAlias)) {
-            if (streamAlias == AudioSystem.STREAM_MUSIC) {
-                setSystemAudioMute(state);
-            }
-            for (int stream = 0; stream < mStreamStates.length; stream++) {
-                if (streamAlias == mStreamVolumeAlias[stream]) {
-                    mStreamStates[stream].mute(cb, state);
-
-                    Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
-                    intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream);
-                    intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
-                    sendBroadcastToAll(intent);
-                }
-            }
-        }
-    }
-
     private void setSystemAudioMute(boolean state) {
         if (mHdmiManager == null || mHdmiTvClient == null) return;
         synchronized (mHdmiManager) {
@@ -1561,7 +1587,7 @@
             streamType = getActiveStreamType(streamType);
         }
         synchronized (VolumeStreamState.class) {
-            return mStreamStates[streamType].isMuted_syncVSS();
+            return mStreamStates[streamType].mIsMuted;
         }
     }
 
@@ -1665,20 +1691,17 @@
         }
     }
 
-    /** @see AudioManager#setMasterMute(boolean, int) */
-    public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) {
-        setMasterMuteInternal(state, flags, callingPackage, cb, Binder.getCallingUid());
-    }
-
-    private void setMasterMuteInternal(boolean state, int flags, String callingPackage, IBinder cb,
-            int uid) {
-        if (mUseFixedVolume) {
-            return;
-        }
+    private void setMasterMuteInternal(int adjust, int flags, String callingPackage, int uid) {
         if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
                 != AppOpsManager.MODE_ALLOWED) {
             return;
         }
+        boolean state;
+        if (adjust == AudioManager.ADJUST_TOGGLE_MUTE) {
+            state = !AudioSystem.getMasterMute();
+        } else {
+            state = adjust == AudioManager.ADJUST_MUTE;
+        }
         if (state != AudioSystem.getMasterMute()) {
             setSystemAudioMute(state);
             AudioSystem.setMasterMute(state);
@@ -1714,7 +1737,7 @@
             int index = mStreamStates[streamType].getIndex(device);
 
             // by convention getStreamVolume() returns 0 when a stream is muted.
-            if (mStreamStates[streamType].isMuted_syncVSS()) {
+            if (mStreamStates[streamType].mIsMuted) {
                 index = 0;
             }
             if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
@@ -1934,11 +1957,11 @@
                         }
                     }
                 }
-                mStreamStates[streamType].mute(null, false);
+                mStreamStates[streamType].mute(false);
                 mRingerModeMutedStreams &= ~(1 << streamType);
             } else {
                 // mute
-                mStreamStates[streamType].mute(null, true);
+                mStreamStates[streamType].mute(true);
                 mRingerModeMutedStreams |= (1 << streamType);
             }
         }
@@ -2426,13 +2449,9 @@
             streamState.readSettings();
             synchronized (VolumeStreamState.class) {
                 // unmute stream that was muted but is not affect by mute anymore
-                if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) &&
+                if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
                         !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
-                    int size = streamState.mDeathHandlers.size();
-                    for (int i = 0; i < size; i++) {
-                        streamState.mDeathHandlers.get(i).mMuteCount = 1;
-                        streamState.mDeathHandlers.get(i).mute_syncVSS(false);
-                    }
+                    streamState.mIsMuted = false;
                 }
             }
         }
@@ -3221,8 +3240,16 @@
     }
 
     private void ensureValidDirection(int direction) {
-        if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {
-            throw new IllegalArgumentException("Bad direction " + direction);
+        switch (direction) {
+            case AudioManager.ADJUST_LOWER:
+            case AudioManager.ADJUST_RAISE:
+            case AudioManager.ADJUST_SAME:
+            case AudioManager.ADJUST_MUTE:
+            case AudioManager.ADJUST_UNMUTE:
+            case AudioManager.ADJUST_TOGGLE_MUTE:
+                break;
+            default:
+                throw new IllegalArgumentException("Bad direction " + direction);
         }
     }
 
@@ -3238,6 +3265,11 @@
         }
     }
 
+    private boolean isMuteAdjust(int adjust) {
+        return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
+                || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
+    }
+
     private boolean isInCommunication() {
         boolean IsInCall = false;
 
@@ -3418,14 +3450,32 @@
         return device;
     }
 
-    public void setWiredDeviceConnectionState(int device, int state, String name) {
+    /*
+     * A class just for packaging up a set of connection parameters.
+     */
+    private class WiredDeviceConnectionState {
+        public int mType;
+        public int mState;
+        public String mAddress;
+        public String mName;
+
+        public WiredDeviceConnectionState(int type, int state, String address, String name) {
+            mType = type;
+            mState = state;
+            mAddress = address;
+            mName = name;
+        }
+    }
+
+    public void setWiredDeviceConnectionState(int type, int state, String address,
+            String name) {
         synchronized (mConnectedDevices) {
-            int delay = checkSendBecomingNoisyIntent(device, state);
+            int delay = checkSendBecomingNoisyIntent(type, state);
             queueMsgUnderWakeLock(mAudioHandler,
                     MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
-                    device,
-                    state,
-                    name,
+                    0,
+                    0,
+                    new WiredDeviceConnectionState(type, state, address, name),
                     delay);
         }
     }
@@ -3467,11 +3517,11 @@
     public class VolumeStreamState {
         private final int mStreamType;
 
+        private boolean mIsMuted;
         private String mVolumeIndexSettingName;
         private int mIndexMax;
         private final ConcurrentHashMap<Integer, Integer> mIndex =
                                             new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
-        private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death
 
         private VolumeStreamState(String settingName, int streamType) {
 
@@ -3482,9 +3532,6 @@
             AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
             mIndexMax *= 10;
 
-            // mDeathHandlers must be created before calling readSettings()
-            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
-
             readSettings();
         }
 
@@ -3549,7 +3596,7 @@
         // must be called while synchronized VolumeStreamState.class
         public void applyDeviceVolume_syncVSS(int device) {
             int index;
-            if (isMuted_syncVSS()) {
+            if (mIsMuted) {
                 index = 0;
             } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
                     || ((device & mFullVolumeDevices) != 0)) {
@@ -3565,7 +3612,7 @@
                 // apply default volume first: by convention this will reset all
                 // devices volumes in audio policy manager to the supplied value
                 int index;
-                if (isMuted_syncVSS()) {
+                if (mIsMuted) {
                     index = 0;
                 } else {
                     index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
@@ -3578,7 +3625,7 @@
                     Map.Entry entry = (Map.Entry)i.next();
                     int device = ((Integer)entry.getKey()).intValue();
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
-                        if (isMuted_syncVSS()) {
+                        if (mIsMuted) {
                             index = 0;
                         } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
                                 mAvrcpAbsVolSupported)
@@ -3688,14 +3735,20 @@
             }
         }
 
-        public void mute(IBinder cb, boolean state) {
+        public void mute(boolean state) {
             synchronized (VolumeStreamState.class) {
-                VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state);
-                if (handler == null) {
-                    Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
-                    return;
+                if (state != mIsMuted) {
+                    mIsMuted = state;
+                    // Set the new mute volume. This propagates the values to
+                    // the audio system, otherwise the volume won't be changed
+                    // at the lower level.
+                    sendMsg(mAudioHandler,
+                            MSG_SET_ALL_VOLUMES,
+                            SENDMSG_QUEUE,
+                            0,
+                            0,
+                            this, 0);
                 }
-                handler.mute_syncVSS(state);
             }
         }
 
@@ -3733,117 +3786,9 @@
             return index;
         }
 
-        private class VolumeDeathHandler implements IBinder.DeathRecipient {
-            private IBinder mICallback; // To be notified of client's death
-            private int mMuteCount; // Number of active mutes for this client
-
-            VolumeDeathHandler(IBinder cb) {
-                mICallback = cb;
-            }
-
-            // must be called while synchronized VolumeStreamState.class
-            public void mute_syncVSS(boolean state) {
-                boolean updateVolume = false;
-                if (state) {
-                    if (mMuteCount == 0) {
-                        // Register for client death notification
-                        try {
-                            // mICallback can be 0 if muted by AudioService
-                            if (mICallback != null) {
-                                mICallback.linkToDeath(this, 0);
-                            }
-                            VolumeStreamState.this.mDeathHandlers.add(this);
-                            // If the stream is not yet muted by any client, set level to 0
-                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
-                                updateVolume = true;
-                            }
-                        } catch (RemoteException e) {
-                            // Client has died!
-                            binderDied();
-                            return;
-                        }
-                    } else {
-                        Log.w(TAG, "stream: "+mStreamType+" was already muted by this client");
-                    }
-                    mMuteCount++;
-                } else {
-                    if (mMuteCount == 0) {
-                        Log.e(TAG, "unexpected unmute for stream: "+mStreamType);
-                    } else {
-                        mMuteCount--;
-                        if (mMuteCount == 0) {
-                            // Unregister from client death notification
-                            VolumeStreamState.this.mDeathHandlers.remove(this);
-                            // mICallback can be 0 if muted by AudioService
-                            if (mICallback != null) {
-                                mICallback.unlinkToDeath(this, 0);
-                            }
-                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
-                                updateVolume = true;
-                            }
-                        }
-                    }
-                }
-                if (updateVolume) {
-                    sendMsg(mAudioHandler,
-                            MSG_SET_ALL_VOLUMES,
-                            SENDMSG_QUEUE,
-                            0,
-                            0,
-                            VolumeStreamState.this, 0);
-                }
-            }
-
-            public void binderDied() {
-                Log.w(TAG, "Volume service client died for stream: "+mStreamType);
-                synchronized (VolumeStreamState.class) {
-                    if (mMuteCount != 0) {
-                        // Reset all active mute requests from this client.
-                        mMuteCount = 1;
-                        mute_syncVSS(false);
-                    }
-                }
-            }
-        }
-
-        private int muteCount() {
-            int count = 0;
-            int size = mDeathHandlers.size();
-            for (int i = 0; i < size; i++) {
-                count += mDeathHandlers.get(i).mMuteCount;
-            }
-            return count;
-        }
-
-        // must be called while synchronized VolumeStreamState.class
-        private boolean isMuted_syncVSS() {
-            return muteCount() != 0;
-        }
-
-        // must be called while synchronized VolumeStreamState.class
-        private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) {
-            VolumeDeathHandler handler;
-            int size = mDeathHandlers.size();
-            for (int i = 0; i < size; i++) {
-                handler = mDeathHandlers.get(i);
-                if (cb == handler.mICallback) {
-                    return handler;
-                }
-            }
-            // If this is the first mute request for this client, create a new
-            // client death handler. Otherwise, it is an out of sequence unmute request.
-            if (state) {
-                handler = new VolumeDeathHandler(cb);
-            } else {
-                Log.w(TAG, "stream was not muted by this client");
-                handler = null;
-            }
-            return handler;
-        }
-
         private void dump(PrintWriter pw) {
-            pw.print("   Mute count: ");
-            pw.println(muteCount());
+            pw.print("   Muted: ");
+            pw.println(mIsMuted);
             pw.print("   Max: ");
             pw.println((mIndexMax + 5) / 10);
             pw.print("   Current: ");
@@ -4262,7 +4207,8 @@
                             AudioSystem.setDeviceConnectionState(
                                                             ((Integer)device.getKey()).intValue(),
                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                            (String)device.getValue());
+                                                            (String)device.getValue(),
+                                                            "unknown-device");
                         }
                     }
                     // Restore call state
@@ -4364,8 +4310,12 @@
                     break;
 
                 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
-                    onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
-                    mAudioEventWakeLock.release();
+                    {   WiredDeviceConnectionState connectState =
+                            (WiredDeviceConnectionState)msg.obj;
+                        onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
+                                connectState.mAddress, connectState.mName);
+                        mAudioEventWakeLock.release();
+                    }
                     break;
 
                 case MSG_SET_A2DP_SRC_CONNECTION_STATE:
@@ -4478,7 +4428,8 @@
         setBluetoothA2dpOnInt(true);
         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                 AudioSystem.DEVICE_STATE_AVAILABLE,
-                address);
+                address,
+                "a2dp-device");
         // Reset A2DP suspend state each time a new sink is connected
         AudioSystem.setParameters("A2dpSuspended=false");
         mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
@@ -4496,7 +4447,8 @@
         }
         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                address);
+                address,
+                "a2dp-device");
         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
         synchronized (mCurAudioRoutes) {
             // Remove A2DP routes as well
@@ -4525,7 +4477,8 @@
     private void makeA2dpSrcAvailable(String address) {
         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
                 AudioSystem.DEVICE_STATE_AVAILABLE,
-                address);
+                address,
+                "a2dp-device");
         mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP),
                 address);
     }
@@ -4534,7 +4487,8 @@
     private void makeA2dpSrcUnavailable(String address) {
         AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                address);
+                address,
+                "a2dp-device");
         mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP);
     }
 
@@ -4650,22 +4604,26 @@
         }
     }
 
-    private boolean handleDeviceConnection(boolean connected, int device, String params) {
+    private boolean handleDeviceConnection(boolean connect, int device, String address, String deviceName) {
+        Slog.i(TAG, "handleDeviceConnection(" + connect +
+                " dev:" + Integer.toHexString(device) +
+                " address:" + address + 
+                " name:" + deviceName + ")");
         synchronized (mConnectedDevices) {
             boolean isConnected = (mConnectedDevices.containsKey(device) &&
-                    (params.isEmpty() || mConnectedDevices.get(device).equals(params)));
+                    (address.isEmpty() || mConnectedDevices.get(device).equals(address)));
 
-            if (isConnected && !connected) {
+            if (isConnected && !connect) {
                 AudioSystem.setDeviceConnectionState(device,
                                               AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                              mConnectedDevices.get(device));
+                                              address, deviceName);
                  mConnectedDevices.remove(device);
                  return true;
-            } else if (!isConnected && connected) {
+            } else if (!isConnected && connect) {
                  AudioSystem.setDeviceConnectionState(device,
                                                       AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                      params);
-                 mConnectedDevices.put(new Integer(device), params);
+                                                      address, deviceName);
+                 mConnectedDevices.put(new Integer(device), address);
                  return true;
             }
         }
@@ -4718,12 +4676,18 @@
         return delay;
     }
 
-    private void sendDeviceConnectionIntent(int device, int state, String name)
+    private void sendDeviceConnectionIntent(int device, int state, String address, String deviceName)
     {
+        Slog.i(TAG, "sendDeviceConnectionIntent(dev:0x" + Integer.toHexString(device) +
+                " state:0x" + Integer.toHexString(state) +
+                " address:" + address +
+                " name:" + deviceName + ");");
         Intent intent = new Intent();
 
-        intent.putExtra("state", state);
-        intent.putExtra("name", name);
+        intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
+        intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
+        intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
+
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
 
         int connType = 0;
@@ -4742,6 +4706,8 @@
                 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
             connType = AudioRoutesInfo.MAIN_HDMI;
             configureHdmiPlugIntent(intent, state);
+        } else if (device == AudioSystem.DEVICE_OUT_USB_DEVICE) {
+            connType = AudioRoutesInfo.MAIN_USB;
         }
 
         synchronized (mCurAudioRoutes) {
@@ -4768,8 +4734,14 @@
         }
     }
 
-    private void onSetWiredDeviceConnectionState(int device, int state, String name)
+    private void onSetWiredDeviceConnectionState(int device, int state, String address,
+            String deviceName)
     {
+        Slog.i(TAG, "onSetWiredDeviceConnectionState(dev:" + Integer.toHexString(device)
+                + " state:" + Integer.toHexString(state)
+                + " address:" + address
+                + " deviceName:" + deviceName + ");");
+
         synchronized (mConnectedDevices) {
             if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
@@ -4779,7 +4751,7 @@
             boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
                             (((device & AudioSystem.DEVICE_BIT_IN) != 0) &&
                              ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0));
-            handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
+            handleDeviceConnection(state == 1, device, address, deviceName);
             if (state != 0) {
                 if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
@@ -4817,8 +4789,8 @@
                     }
                 }
             }
-            if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) {
-                sendDeviceConnectionIntent(device, state, name);
+            if (!isUsb && device != AudioSystem.DEVICE_IN_WIRED_HEADSET) {
+                sendDeviceConnectionIntent(device, state, address, deviceName);
             }
         }
     }
@@ -4942,8 +4914,9 @@
                 }
 
                 boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
-                boolean success = handleDeviceConnection(connected, outDevice, address) &&
-                                      handleDeviceConnection(connected, inDevice, address);
+                boolean success =
+                    handleDeviceConnection(connected, outDevice, address, "Bluetooth Headset") &&
+                    handleDeviceConnection(connected, inDevice, address, "Bluetooth Headset");
                 if (success) {
                     synchronized (mScoClients) {
                         if (connected) {
@@ -5648,7 +5621,10 @@
                     Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
         }
 
-        public boolean suppressAdjustment(int resolvedStream, int flags) {
+        public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
+            if (isMute) {
+                return false;
+            }
             boolean suppress = false;
             if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
                 final long now = SystemClock.uptimeMillis();
@@ -5801,12 +5777,6 @@
         public void setRingerModeInternal(int ringerMode, String caller) {
             AudioService.this.setRingerModeInternal(ringerMode, caller);
         }
-
-        @Override
-        public void setMasterMuteForUid(boolean state, int flags, String callingPackage, IBinder cb,
-                int uid) {
-            setMasterMuteInternal(state, flags, callingPackage, cb, uid);
-        }
     }
 
     //==========================================================================================
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 46ab7e0..7084656 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -534,7 +534,8 @@
     public static final int SYNC_EVENT_NONE = 0;
     public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1;
 
-    public static native int setDeviceConnectionState(int device, int state, String device_address);
+    public static native int setDeviceConnectionState(int device, int state,
+                                                      String device_address, String device_name);
     public static native int getDeviceConnectionState(int device, String device_address);
     public static native int setPhoneState(int state);
     public static native int setForceUse(int usage, int config);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1af0372..caccb6e 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1237,8 +1237,14 @@
 
     /**
      * Flushes the audio data currently queued for playback. Any data that has
-     * not been played back will be discarded.  No-op if not stopped or paused,
+     * been written but not yet presented will be discarded.  No-op if not stopped or paused,
      * or if the track's creation mode is not {@link #MODE_STREAM}.
+     * <BR> Note that although data written but not yet presented is discarded, there is no
+     * guarantee that all of the buffer space formerly used by that data
+     * is available for a subsequent write.
+     * For example, a call to {@link #write(byte[], int, int)} with <code>sizeInBytes</code>
+     * less than or equal to the total buffer size
+     * may return a short actual transfer count.
      */
     public void flush() {
         if (mState == STATE_INITIALIZED) {
diff --git a/media/java/android/media/ClosedCaptionRenderer.java b/media/java/android/media/ClosedCaptionRenderer.java
index ec33c5c..d34b21b 100644
--- a/media/java/android/media/ClosedCaptionRenderer.java
+++ b/media/java/android/media/ClosedCaptionRenderer.java
@@ -666,7 +666,7 @@
             if (pac.isIndentPAC()) {
                 moveCursorTo(pac.getRow(), pac.getCol());
             } else {
-                moveCursorToRow(pac.getRow());
+                moveCursorTo(pac.getRow(), 1);
             }
             getLineBuffer(mRow).setPACAt(mCol, pac);
         }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index fad3cec..dabd9c2 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -52,16 +52,10 @@
 
     void setMasterVolume(int index, int flags, String callingPackage);
 
-    void setStreamSolo(int streamType, boolean state, IBinder cb);
-
-    void setStreamMute(int streamType, boolean state, IBinder cb);
-
     boolean isStreamMute(int streamType);
 
     void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb);
 
-    void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb);
-
     boolean isMasterMute();
 
     int getStreamVolume(int streamType);
@@ -195,7 +189,7 @@
     IRingtonePlayer getRingtonePlayer();
     int getMasterStreamType();
 
-    void setWiredDeviceConnectionState(int device, int state, String name);
+    void setWiredDeviceConnectionState(int type, int state, String address, String name);
     int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile);
 
     AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index e74399c..6ac854f 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -881,8 +881,8 @@
                         (int)(mAspectRatioRange.getUpper().doubleValue() * height));
                 return range;
             } catch (IllegalArgumentException e) {
-                // should not be here
-                Log.w(TAG, "could not get supported widths for " + height , e);
+                // height is not supported because there are no suitable widths
+                Log.v(TAG, "could not get supported widths for " + height);
                 throw new IllegalArgumentException("unsupported height");
             }
         }
@@ -925,8 +925,8 @@
                         (int)(width / mAspectRatioRange.getLower().doubleValue()));
                 return range;
             } catch (IllegalArgumentException e) {
-                // should not be here
-                Log.w(TAG, "could not get supported heights for " + width , e);
+                // width is not supported because there are no suitable heights
+                Log.v(TAG, "could not get supported heights for " + width);
                 throw new IllegalArgumentException("unsupported width");
             }
         }
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 7ea269b..4ea22f9 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -221,14 +221,10 @@
                 mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                         direction, flags);
             } else if (isMute) {
-                if (down) {
-                    // We need to send two volume events on down, one to mute
-                    // and one to show the UI
+                if (down && keyEvent.getRepeatCount() == 0) {
                     mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
-                            MediaSessionManager.DIRECTION_MUTE, flags);
+                            AudioManager.ADJUST_TOGGLE_MUTE, flags);
                 }
-                mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
-                        0 /* direction, causes UI to show on down */, flags);
             }
         }
     }
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index a4ef851..b4fff8f 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -59,14 +59,6 @@
     private Context mContext;
 
     /**
-     * Special flag for sending the mute key to dispatchAdjustVolume used by the
-     * system.
-     *
-     * @hide
-     */
-    public static final int DIRECTION_MUTE = -99;
-
-    /**
      * @hide
      */
     public MediaSessionManager(Context context) {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 5b92266..bc9722e 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -756,8 +756,9 @@
          * </p><p>
          * Note that this sub-directory also supports opening the logo as an asset file in write
          * mode.  Callers can create or replace the primary logo associated with this channel by
-         * opening the asset file and writing the full-size photo contents into it.  When the file
-         * is closed, the image will be parsed, sized down if necessary, and stored.
+         * opening the asset file and writing the full-size photo contents into it. (Make sure there
+         * is no padding around the logo image.) When the file is closed, the image will be parsed,
+         * sized down if necessary, and stored.
          * </p><p>
          * Usage example:
          * <pre>
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index ea33a2f..e101709 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -232,28 +232,28 @@
                         env,
                         hashMap,
                         hashMapPutID,
-                        StringPrintf("%s-left", key).c_str(),
+                        AStringPrintf("%s-left", key).c_str(),
                         left);
 
                 SetMapInt32(
                         env,
                         hashMap,
                         hashMapPutID,
-                        StringPrintf("%s-top", key).c_str(),
+                        AStringPrintf("%s-top", key).c_str(),
                         top);
 
                 SetMapInt32(
                         env,
                         hashMap,
                         hashMapPutID,
-                        StringPrintf("%s-right", key).c_str(),
+                        AStringPrintf("%s-right", key).c_str(),
                         right);
 
                 SetMapInt32(
                         env,
                         hashMap,
                         hashMapPutID,
-                        StringPrintf("%s-bottom", key).c_str(),
+                        AStringPrintf("%s-bottom", key).c_str(),
                         bottom);
                 break;
             }
diff --git a/packages/Keyguard/res/layout/keyguard_host_view.xml b/packages/Keyguard/res/layout/keyguard_host_view.xml
index 3635aff..7291cd4 100644
--- a/packages/Keyguard/res/layout/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_host_view.xml
@@ -26,7 +26,9 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:clipChildren="false"
-    android:clipToPadding="false">
+    android:clipToPadding="false"
+    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
+                                                  from this view when bouncer is shown -->
 
     <com.android.keyguard.KeyguardSecurityContainer
         android:id="@+id/keyguard_security_container"
diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
index d8b0c71..c023dc6 100644
--- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java
+++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
@@ -41,7 +41,8 @@
 
     private static CharSequence mSeparator;
 
-    private LockPatternUtils mLockPatternUtils;
+    private final boolean mIsEmergencyCallCapable;
+
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
@@ -78,7 +79,8 @@
 
     public CarrierText(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mLockPatternUtils = new LockPatternUtils(mContext);
+        mIsEmergencyCallCapable = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_voice_capable);
         boolean useAllCaps;
         TypedArray a = context.getTheme().obtainStyledAttributes(
                 attrs, R.styleable.CarrierText, 0, 0);
@@ -222,7 +224,7 @@
      */
     private CharSequence makeCarrierStringOnEmergencyCapable(
             CharSequence simMessage, CharSequence emergencyCallMessage) {
-        if (mLockPatternUtils.isEmergencyCallCapable()) {
+        if (mIsEmergencyCallCapable) {
             return concatenate(simMessage, emergencyCallMessage);
         }
         return simMessage;
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 50ac261..3627e3e 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -21,7 +21,7 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.telephony.TelephonyManager;
+import android.telecom.TelecomManager;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.Button;
@@ -50,8 +50,17 @@
             updateEmergencyCallButton();
         }
     };
+
+    public interface EmergencyButtonCallback {
+        public void onEmergencyButtonClickedWhenInCall();
+    }
+
     private LockPatternUtils mLockPatternUtils;
     private PowerManager mPowerManager;
+    private EmergencyButtonCallback mEmergencyButtonCallback;
+
+    private final boolean mIsVoiceCapable;
+    private final boolean mEnableEmergencyCallWhileSimLocked;
 
     public EmergencyButton(Context context) {
         this(context, null);
@@ -59,6 +68,10 @@
 
     public EmergencyButton(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mIsVoiceCapable = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_voice_capable);
+        mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
     }
 
     @Override
@@ -93,8 +106,11 @@
         // TODO: implement a shorter timeout once new PowerManager API is ready.
         // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
         mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
-        if (mLockPatternUtils.isInCall()) {
-            mLockPatternUtils.resumeCall();
+        if (isInCall()) {
+            resumeCall();
+            if (mEmergencyButtonCallback != null) {
+                mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
+            }
         } else {
             final boolean bypassHandler = true;
             KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(bypassHandler);
@@ -107,21 +123,57 @@
     }
 
     private void updateEmergencyCallButton() {
-        boolean enabled = false;
-        if (mLockPatternUtils.isInCall()) {
-            enabled = true; // always show "return to call" if phone is off-hook
-        } else if (mLockPatternUtils.isEmergencyCallCapable()) {
-            final boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext).isSimPinVoiceSecure();
-            if (simLocked) {
-                // Some countries can't handle emergency calls while SIM is locked.
-                enabled = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+        boolean visible = false;
+        if (mIsVoiceCapable) {
+            // Emergency calling requires voice capability.
+            if (isInCall()) {
+                visible = true; // always show "return to call" if phone is off-hook
             } else {
-                // True if we need to show a secure screen (pin/pattern/SIM pin/SIM puk);
-                // hides emergency button on "Slide" screen if device is not secure.
-                enabled = mLockPatternUtils.isSecure();
+                final boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext)
+                        .isSimPinVoiceSecure();
+                if (simLocked) {
+                    // Some countries can't handle emergency calls while SIM is locked.
+                    visible = mEnableEmergencyCallWhileSimLocked;
+                } else {
+                    // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk);
+                    visible = mLockPatternUtils.isSecure();
+                }
             }
         }
-        mLockPatternUtils.updateEmergencyCallButtonState(this, enabled, false);
+        if (visible) {
+            setVisibility(View.VISIBLE);
+
+            int textId;
+            if (isInCall()) {
+                textId = com.android.internal.R.string.lockscreen_return_to_call;
+            } else {
+                textId = com.android.internal.R.string.lockscreen_emergency_call;
+            }
+            setText(textId);
+        } else {
+            setVisibility(View.GONE);
+        }
     }
 
+    public void setCallback(EmergencyButtonCallback callback) {
+        mEmergencyButtonCallback = callback;
+    }
+
+    /**
+     * Resumes a call in progress.
+     */
+    private void resumeCall() {
+        getTelecommManager().showInCallScreen(false);
+    }
+
+    /**
+     * @return {@code true} if there is a call currently in progress.
+     */
+    private boolean isInCall() {
+        return getTelecommManager().isInCall();
+    }
+
+    private TelecomManager getTelecommManager() {
+        return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index b03176c..b2e4728 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -32,7 +32,7 @@
  * Base class for PIN and password unlock screens.
  */
 public abstract class KeyguardAbsKeyInputView extends LinearLayout
-        implements KeyguardSecurityView {
+        implements KeyguardSecurityView, EmergencyButton.EmergencyButtonCallback {
     protected KeyguardSecurityCallback mCallback;
     protected LockPatternUtils mLockPatternUtils;
     protected SecurityMessageDisplay mSecurityMessageDisplay;
@@ -85,6 +85,15 @@
         mLockPatternUtils = new LockPatternUtils(mContext);
         mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
+
+        EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
+        if (button != null) {
+            button.setCallback(this);
+        }
+    }
+
+    public void onEmergencyButtonClickedWhenInCall() {
+        mCallback.reset();
     }
 
     /*
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index c7bc04d..10ce426 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -29,6 +29,7 @@
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
 import com.android.internal.widget.LockPatternUtils;
@@ -153,6 +154,16 @@
         return false;
     }
 
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            event.getText().add(mSecurityContainer.getCurrentSecurityModeContentDescription());
+            return true;
+        } else {
+            return super.dispatchPopulateAccessibilityEvent(event);
+        }
+    }
+
     protected KeyguardSecurityContainer getSecurityContainer() {
         return mSecurityContainer;
     }
@@ -185,6 +196,11 @@
     }
 
     @Override
+    public void reset() {
+        mViewMediatorCallback.resetKeyguard();
+    }
+
+    @Override
     public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
         if (mViewMediatorCallback != null) {
             mViewMediatorCallback.setNeedsInput(needsInput);
@@ -416,6 +432,4 @@
     public SecurityMode getCurrentSecurityMode() {
         return mSecurityContainer.getCurrentSecurityMode();
     }
-
-
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 62f1b69..9aa5729 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -38,7 +38,8 @@
 import java.util.List;
 
 public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView,
-        AppearAnimationCreator<LockPatternView.CellState> {
+        AppearAnimationCreator<LockPatternView.CellState>,
+        EmergencyButton.EmergencyButtonCallback {
 
     private static final String TAG = "SecurityPatternView";
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -140,6 +141,15 @@
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
         mContainer = (ViewGroup) findViewById(R.id.container);
         mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area);
+
+        EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
+        if (button != null) {
+            button.setCallback(this);
+        }
+    }
+
+    public void onEmergencyButtonClickedWhenInCall() {
+        mCallback.reset();
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java
index 8bb8805..5877bc8 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -40,4 +40,8 @@
      */
     void reportUnlockAttempt(boolean success);
 
+    /**
+     * Resets the keyguard view.
+     */
+    void reset();
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 61eef48..41ec3b0 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -55,6 +55,7 @@
         public void userActivity();
         public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
         public void finish();
+        public void reset();
     }
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
@@ -111,6 +112,14 @@
         }
     }
 
+    public CharSequence getCurrentSecurityModeContentDescription() {
+        View v = (View) getSecurityView(mCurrentSecuritySelection);
+        if (v != null) {
+            return v.getContentDescription();
+        }
+        return "";
+    }
+
     private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
         final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
         KeyguardSecurityView view = null;
@@ -406,7 +415,6 @@
     }
 
     private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
-
         public void userActivity() {
             if (mSecurityCallback != null) {
                 mSecurityCallback.userActivity();
@@ -431,6 +439,9 @@
             }
         }
 
+        public void reset() {
+            mSecurityCallback.reset();
+        }
     };
 
     // The following is used to ignore callbacks from SecurityViews that are no longer current
@@ -445,6 +456,8 @@
         public boolean isVerifyUnlockOnly() { return false; }
         @Override
         public void dismiss(boolean securityVerified) { }
+        @Override
+        public void reset() {}
     };
 
     private int getSecurityViewIdForMode(SecurityMode securityMode) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 107f417..3eb31ad 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -17,20 +17,16 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
 
-import java.util.List;
-
 public class KeyguardSecurityModel {
 
     /**
-     * The different types of security available for {@link Mode#UnlockScreen}.
-     * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
+     * The different types of security available.
+     * @see KeyguardSecurityContainer#showSecurityScreen
      */
     public enum SecurityMode {
         Invalid, // NULL state
@@ -42,12 +38,16 @@
         SimPuk // Unlock by entering a sim puk
     }
 
-    private Context mContext;
+    private final Context mContext;
+    private final boolean mIsPukScreenAvailable;
+
     private LockPatternUtils mLockPatternUtils;
 
     KeyguardSecurityModel(Context context) {
         mContext = context;
         mLockPatternUtils = new LockPatternUtils(context);
+        mIsPukScreenAvailable = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enable_puk_unlock_screen);
     }
 
     void setLockPatternUtils(LockPatternUtils utils) {
@@ -56,39 +56,35 @@
 
     SecurityMode getSecurityMode() {
         KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
-        SecurityMode mode = SecurityMode.None;
+
         if (SubscriptionManager.isValidSubscriptionId(
                 monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED))) {
-            mode = SecurityMode.SimPin;
-        } else if (SubscriptionManager.isValidSubscriptionId(
-                    monitor.getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED))
-                && mLockPatternUtils.isPukUnlockScreenEnable()) {
-            mode = SecurityMode.SimPuk;
-        } else {
-            final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
-            switch (security) {
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
-                    mode = mLockPatternUtils.isLockPasswordEnabled() ?
-                            SecurityMode.PIN : SecurityMode.None;
-                    break;
-                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
-                    mode = mLockPatternUtils.isLockPasswordEnabled() ?
-                            SecurityMode.Password : SecurityMode.None;
-                    break;
-
-                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
-                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
-                    mode = mLockPatternUtils.isLockPatternEnabled() ?
-                            SecurityMode.Pattern : SecurityMode.None;
-                    break;
-
-                default:
-                    throw new IllegalStateException("Unknown security quality:" + security);
-            }
+            return SecurityMode.SimPin;
         }
-        return mode;
+
+        if (mIsPukScreenAvailable && SubscriptionManager.isValidSubscriptionId(
+                monitor.getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED))) {
+            return SecurityMode.SimPuk;
+        }
+
+        final int security = mLockPatternUtils.getActivePasswordQuality();
+        switch (security) {
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+                return SecurityMode.PIN;
+
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+                return SecurityMode.Password;
+
+            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                return SecurityMode.Pattern;
+            case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+                return SecurityMode.None;
+
+            default:
+                throw new IllegalStateException("Unknown security quality:" + security);
+        }
     }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index f327078..5bbcc8c 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -62,6 +62,11 @@
     void readyForKeyguardDone();
 
     /**
+     * Reset the keyguard and bouncer.
+     */
+    void resetKeyguard();
+
+    /**
      * Play the "device trusted" sound.
      */
     void playTrustedSound();
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index 0bf64aa..a87afe0 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -159,6 +159,34 @@
                 android:layout_marginEnd="16dip"
                 android:orientation="vertical">
 
+                <!-- Duplex -->
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dip"
+                    android:layout_marginStart="12dip"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:labelFor="@+id/duplex_spinner"
+                    android:text="@string/label_duplex">
+                </TextView>
+
+                <Spinner
+                    android:id="@+id/duplex_spinner"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginStart="4dip">
+                </Spinner>
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dip"
+                android:layout_marginEnd="16dip"
+                android:orientation="vertical">
+
                 <!-- Range options -->
 
                 <TextView
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 1a840e3..923a38c 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papiergrootte"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papiergrootte:"</string>
     <string name="label_color" msgid="1108690305218188969">"Kleur"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Oriëntasie"</string>
     <string name="label_pages" msgid="7768589729282182230">"Bladsye"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Al <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Swart en wit"</item>
     <item msgid="2762241247228983754">"Kleur"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Geen"</item>
+    <item msgid="7296563835355641719">"Lang rand"</item>
+    <item msgid="79513688117503758">"Kort rand"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portret"</item>
     <item msgid="3199660090246166812">"Landskap"</item>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index 683d585..8f462497 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"የወረቀት መጠን"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"የወረቀት መጠን፦"</string>
     <string name="label_color" msgid="1108690305218188969">"ቀለም"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"አቀማመጠ ገፅ"</string>
     <string name="label_pages" msgid="7768589729282182230">"ገፆች"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ሁሉም <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -33,7 +35,7 @@
     <string name="install_for_print_preview" msgid="6366303997385509332">"ለቅድመ-እይታ የፒ ዲ ኤፍ መመልከቻ ይጫኑ"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"የአታሚ መተግበሪያ ተበላሽቷል"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"የህትመት ስራን በማመንጨት ላይ"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"እንደ ፒዲኤፍ አስቀምጥ"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"እንደ PDF አስቀምጥ"</string>
     <string name="all_printers" msgid="5018829726861876202">"ሁሉም አታሚዎች…"</string>
     <string name="print_dialog" msgid="32628687461331979">"የህትመት መገናኛ"</string>
     <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"ጥቁር እና ነጭ"</item>
     <item msgid="2762241247228983754">"ቀለም"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"ምንም"</item>
+    <item msgid="7296563835355641719">"ረጅም ጠርዝ"</item>
+    <item msgid="79513688117503758">"አጭር ጠርዝ"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"የቁም"</item>
     <item msgid="3199660090246166812">"የወርድ"</item>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 0a7d301..9f931d5 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"حجم الورق"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"حجم الورق:"</string>
     <string name="label_color" msgid="1108690305218188969">"ألوان"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"الاتجاه"</string>
     <string name="label_pages" msgid="7768589729282182230">"الصفحات"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"جميع الصفحات وعددها <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"أبيض وأسود"</item>
     <item msgid="2762241247228983754">"ملونة"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"لا شيء"</item>
+    <item msgid="7296563835355641719">"حافة طويلة"</item>
+    <item msgid="79513688117503758">"حافة قصيرة"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"عمودي"</item>
     <item msgid="3199660090246166812">"أفقي"</item>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 8792349..981b4c1 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Размер на хартията"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Размер на хартията:"</string>
     <string name="label_color" msgid="1108690305218188969">"Цвят"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
     <string name="label_pages" msgid="7768589729282182230">"Страници"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Всички <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Черно-бяло"</item>
     <item msgid="2762241247228983754">"Цветно"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Без"</item>
+    <item msgid="7296563835355641719">"Дълъг ръб"</item>
+    <item msgid="79513688117503758">"Къс ръб"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Вертикално"</item>
     <item msgid="3199660090246166812">"Хоризонтално"</item>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index 5c5fabf..4d74ceb 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"কাগজের আকার"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"কাগজের আকার:"</string>
     <string name="label_color" msgid="1108690305218188969">"রঙ"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"সজ্জা"</string>
     <string name="label_pages" msgid="7768589729282182230">"পৃষ্ঠাগুলি"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"সমস্ত <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"কালো এবং সাদা"</item>
     <item msgid="2762241247228983754">"রঙ"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"প্রতিকৃতি"</item>
     <item msgid="3199660090246166812">"ভূদৃশ্য"</item>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index a9677cb..ca7bafa 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Mida del paper"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Mida del paper:"</string>
     <string name="label_color" msgid="1108690305218188969">"Color"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientació"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pàgines"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Totes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Blanc i negre"</item>
     <item msgid="2762241247228983754">"Color"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Cap"</item>
+    <item msgid="7296563835355641719">"Costat llarg"</item>
+    <item msgid="79513688117503758">"Costat curt"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Vertical"</item>
     <item msgid="3199660090246166812">"Horitzontal"</item>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 791e485..77f338a 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Velikost papíru"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Velikost papíru:"</string>
     <string name="label_color" msgid="1108690305218188969">"Barva"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientace"</string>
     <string name="label_pages" msgid="7768589729282182230">"Stránky"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Vše: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Černobíle"</item>
     <item msgid="2762241247228983754">"Barevně"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Žádné"</item>
+    <item msgid="7296563835355641719">"Dlouhý okraj"</item>
+    <item msgid="79513688117503758">"Krátký okraj"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Na výšku"</item>
     <item msgid="3199660090246166812">"Na šířku"</item>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index c4a383e..b497c18 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papirstørrelse"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papirstørrelse:"</string>
     <string name="label_color" msgid="1108690305218188969">"Farve"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Retning"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sider"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Sort/hvid"</item>
     <item msgid="2762241247228983754">"Farve"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ingen"</item>
+    <item msgid="7296563835355641719">"Den lange led"</item>
+    <item msgid="79513688117503758">"Den korte led"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Stående"</item>
     <item msgid="3199660090246166812">"Liggende"</item>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index 43be3dc..1b9ce09 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papierformat"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papierformat:"</string>
     <string name="label_color" msgid="1108690305218188969">"Farbe"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Ausrichtung"</string>
     <string name="label_pages" msgid="7768589729282182230">"Seiten"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Schwarz-weiß"</item>
     <item msgid="2762241247228983754">"Farbe"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ohne"</item>
+    <item msgid="7296563835355641719">"Lange Seite"</item>
+    <item msgid="79513688117503758">"Kurze Seite"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Hochformat"</item>
     <item msgid="3199660090246166812">"Querformat"</item>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index 25f609b..2908b6a 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Μεγέθος χαρτιού"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Μέγεθος χαρτιού:"</string>
     <string name="label_color" msgid="1108690305218188969">"Χρώμα"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Προσανατολισμός"</string>
     <string name="label_pages" msgid="7768589729282182230">"Σελίδες"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Και οι <xliff:g id="PAGE_COUNT">%1$s</xliff:g> σελίδες"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Ασπρόμαυρο"</item>
     <item msgid="2762241247228983754">"Χρώμα"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Κανένα"</item>
+    <item msgid="7296563835355641719">"Μεγάλη πλευρά"</item>
+    <item msgid="79513688117503758">"Μικρή πλευρά"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Πορτραίτο"</item>
     <item msgid="3199660090246166812">"Οριζόντια"</item>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 2198c7a..5fa5338 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Paper size"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Paper size:"</string>
     <string name="label_color" msgid="1108690305218188969">"Colour"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"All <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Black &amp; White"</item>
     <item msgid="2762241247228983754">"Colour"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"None"</item>
+    <item msgid="7296563835355641719">"Long edge"</item>
+    <item msgid="79513688117503758">"Short edge"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portrait"</item>
     <item msgid="3199660090246166812">"Landscape"</item>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 2198c7a..5fa5338 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Paper size"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Paper size:"</string>
     <string name="label_color" msgid="1108690305218188969">"Colour"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"All <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Black &amp; White"</item>
     <item msgid="2762241247228983754">"Colour"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"None"</item>
+    <item msgid="7296563835355641719">"Long edge"</item>
+    <item msgid="79513688117503758">"Short edge"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portrait"</item>
     <item msgid="3199660090246166812">"Landscape"</item>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index e194f55..17ea709 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Tamaño del papel"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Tamaño de papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Color"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Blanco y negro"</item>
     <item msgid="2762241247228983754">"Color"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ninguno"</item>
+    <item msgid="7296563835355641719">"Borde largo"</item>
+    <item msgid="79513688117503758">"Borde corto"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Vertical"</item>
     <item msgid="3199660090246166812">"Horizontal"</item>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index b0ab529..c597177 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Tamaño del papel"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Tamaño del papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Color"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Blanco y negro"</item>
     <item msgid="2762241247228983754">"Color"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ninguna"</item>
+    <item msgid="7296563835355641719">"Borde largo"</item>
+    <item msgid="79513688117503758">"Borde corto"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Vertical"</item>
     <item msgid="3199660090246166812">"Horizontal"</item>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 6e75bbb..5e300da 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Paberi suurus"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Paberi suurus:"</string>
     <string name="label_color" msgid="1108690305218188969">"Värv"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Suund"</string>
     <string name="label_pages" msgid="7768589729282182230">"Lehed"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Kõik <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Mustvalge"</item>
     <item msgid="2762241247228983754">"Värv"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Puudub"</item>
+    <item msgid="7296563835355641719">"Pikk serv"</item>
+    <item msgid="79513688117503758">"Lühike serv"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Vertikaalpaigutus"</item>
     <item msgid="3199660090246166812">"Horisontaalpaigutus"</item>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index 4f0f8fc..4e79c60 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Paperaren tamaina"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Paperaren tamaina:"</string>
     <string name="label_color" msgid="1108690305218188969">"Koloretan"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientazioa"</string>
     <string name="label_pages" msgid="7768589729282182230">"Orriak"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> orriak"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Zuri-beltza"</item>
     <item msgid="2762241247228983754">"Koloretakoa"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Bertikala"</item>
     <item msgid="3199660090246166812">"Horizontala"</item>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index d35a063..1bc934e 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"اندازه کاغذ"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"اندازه کاغذ:"</string>
     <string name="label_color" msgid="1108690305218188969">"رنگی"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"جهت"</string>
     <string name="label_pages" msgid="7768589729282182230">"صفحه‌ها"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"همه <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"سیاه و سفید"</item>
     <item msgid="2762241247228983754">"رنگی"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"هیچ‌کدام"</item>
+    <item msgid="7296563835355641719">"طول"</item>
+    <item msgid="79513688117503758">"عرض"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"عمودی"</item>
     <item msgid="3199660090246166812">"افقی"</item>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index 8e540f9..87dd636 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Paperikoko"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Paperikoko:"</string>
     <string name="label_color" msgid="1108690305218188969">"Väri"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Suunta"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sivut"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Kaikki <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Mustavalkoinen"</item>
     <item msgid="2762241247228983754">"Väri"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ei mitään"</item>
+    <item msgid="7296563835355641719">"Pitkä reuna"</item>
+    <item msgid="79513688117503758">"Lyhyt reuna"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Pysty"</item>
     <item msgid="3199660090246166812">"Vaaka"</item>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 279a467..fe038fd 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Taille du papier"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Taille du papier :"</string>
     <string name="label_color" msgid="1108690305218188969">"Couleur"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Toutes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Noir et blanc"</item>
     <item msgid="2762241247228983754">"Couleur"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Aucune"</item>
+    <item msgid="7296563835355641719">"Bord long"</item>
+    <item msgid="79513688117503758">"Bord court"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portrait"</item>
     <item msgid="3199660090246166812">"Paysage"</item>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index ebfd5de..23aaf51 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Taille du papier"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Taille du papier :"</string>
     <string name="label_color" msgid="1108690305218188969">"Couleur"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Toutes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Noir et blanc"</item>
     <item msgid="2762241247228983754">"Couleur"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Aucun"</item>
+    <item msgid="7296563835355641719">"Bord long"</item>
+    <item msgid="79513688117503758">"Bord court"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portrait"</item>
     <item msgid="3199660090246166812">"Paysage"</item>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index 6e542ea..ba8432f 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Tamaño do papel"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Tamaño do papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Cor"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páxinas"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"As <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Branco e negro"</item>
     <item msgid="2762241247228983754">"Cor"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Vertical"</item>
     <item msgid="3199660090246166812">"Horizontal"</item>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index a3f7fef..b39efcb 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"काग़ज़ का आकार"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"काग़ज़ का आकार:"</string>
     <string name="label_color" msgid="1108690305218188969">"रंग"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"अभिविन्‍यास"</string>
     <string name="label_pages" msgid="7768589729282182230">"पृष्ठ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"सभी <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"श्याम और श्वेत"</item>
     <item msgid="2762241247228983754">"रंग"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"कोई नहीं"</item>
+    <item msgid="7296563835355641719">"लंबा सिरा"</item>
+    <item msgid="79513688117503758">"छोटा सिरा"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"पोर्ट्रेट"</item>
     <item msgid="3199660090246166812">"लैंडस्केप"</item>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 8132d21..7e68f09 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Veličina papira"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Veličina papira:"</string>
     <string name="label_color" msgid="1108690305218188969">"U boji"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orijentacija"</string>
     <string name="label_pages" msgid="7768589729282182230">"Stranice"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Sve stranice (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Crno-bijelo"</item>
     <item msgid="2762241247228983754">"U boji"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ništa"</item>
+    <item msgid="7296563835355641719">"Dulji rub"</item>
+    <item msgid="79513688117503758">"Kraći rub"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portret"</item>
     <item msgid="3199660090246166812">"Pejzaž"</item>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 3ebc450..10b351d 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papírméret"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papírméret:"</string>
     <string name="label_color" msgid="1108690305218188969">"Szín"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Tájolás"</string>
     <string name="label_pages" msgid="7768589729282182230">"Oldalak"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Összes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Fekete-fehér"</item>
     <item msgid="2762241247228983754">"Szín"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nincs"</item>
+    <item msgid="7296563835355641719">"Hosszabb él"</item>
+    <item msgid="79513688117503758">"Rövidebb él"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Álló"</item>
     <item msgid="3199660090246166812">"Fekvő"</item>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 5ef15a5c..08cb138 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Թղթի չափը"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Թղթի չափը՝"</string>
     <string name="label_color" msgid="1108690305218188969">"Գույնը"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Դիրքավորում"</string>
     <string name="label_pages" msgid="7768589729282182230">"Էջեր"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Բոլորը՝ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Սև ու սպիտակ"</item>
     <item msgid="2762241247228983754">"Գույնը"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ոչ մեկը"</item>
+    <item msgid="7296563835355641719">"Լայնեզր"</item>
+    <item msgid="79513688117503758">"Կարճեզր"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Դիմանկար"</item>
     <item msgid="3199660090246166812">"Լանդշաֆտ"</item>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 9714b0f..666442c 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Ukuran kertas"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Ukuran kertas:"</string>
     <string name="label_color" msgid="1108690305218188969">"Warna"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
     <string name="label_pages" msgid="7768589729282182230">"Halaman"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Semua dari <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Hitam &amp; Putih"</item>
     <item msgid="2762241247228983754">"Warna"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Tidak ada"</item>
+    <item msgid="7296563835355641719">"Tepi panjang"</item>
+    <item msgid="79513688117503758">"Tepi pendek"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Potret"</item>
     <item msgid="3199660090246166812">"Lanskap"</item>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index 41a047d..bb0c7ca 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Pappírsstærð"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Pappírsstærð:"</string>
     <string name="label_color" msgid="1108690305218188969">"Litur"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Stefna"</string>
     <string name="label_pages" msgid="7768589729282182230">"Síður"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Allar <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Svarthvítt"</item>
     <item msgid="2762241247228983754">"Í lit"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Skammsnið"</item>
     <item msgid="3199660090246166812">"Langsnið"</item>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index 3653c56..39043ee 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Dimensioni carta"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Dimensioni carta:"</string>
     <string name="label_color" msgid="1108690305218188969">"A colori"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientamento"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pagine"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Tutte e <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Bianco e nero"</item>
     <item msgid="2762241247228983754">"A colori"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nessuno"</item>
+    <item msgid="7296563835355641719">"Lato lungo"</item>
+    <item msgid="79513688117503758">"Lato corto"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Verticale"</item>
     <item msgid="3199660090246166812">"Orizzontale"</item>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index ba293a0..1fd68e9 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"גודל נייר"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"גודל נייר:"</string>
     <string name="label_color" msgid="1108690305218188969">"צבע"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"כיוון"</string>
     <string name="label_pages" msgid="7768589729282182230">"עמודים"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"הכל <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"שחור ולבן"</item>
     <item msgid="2762241247228983754">"צבע"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"ללא"</item>
+    <item msgid="7296563835355641719">"צד ארוך"</item>
+    <item msgid="79513688117503758">"צד קצר"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"לאורך"</item>
     <item msgid="3199660090246166812">"לרוחב"</item>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index f3fed3b..3cc7e8e 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"用紙サイズ"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"用紙サイズ:"</string>
     <string name="label_color" msgid="1108690305218188969">"カラー選択"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"ページ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>ページすべて"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"モノクロ"</item>
     <item msgid="2762241247228983754">"カラー"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"なし"</item>
+    <item msgid="7296563835355641719">"長辺"</item>
+    <item msgid="79513688117503758">"短辺"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"縦向き"</item>
     <item msgid="3199660090246166812">"横向き"</item>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 061e9fb..4a55dfe 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"ფურცლის ზომა"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"ფურცლის ზომა:"</string>
     <string name="label_color" msgid="1108690305218188969">"ფერი"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"ორიენტაცია"</string>
     <string name="label_pages" msgid="7768589729282182230">"გვერდები"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ყველა <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"შავ-თეთრი"</item>
     <item msgid="2762241247228983754">"ფერი"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"არც ერთი"</item>
+    <item msgid="7296563835355641719">"გრძელი კიდე"</item>
+    <item msgid="79513688117503758">"მოკლე კიდე"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"პორტრეტი"</item>
     <item msgid="3199660090246166812">"პეიზაჟის რეჟიმი"</item>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index b02714b..362d790 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Қағаз өлшемі"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Қағаз өлшемі:"</string>
     <string name="label_color" msgid="1108690305218188969">"Түс"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Бағыты"</string>
     <string name="label_pages" msgid="7768589729282182230">"Беттер"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Барлық <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Қара &amp; Ақ"</item>
     <item msgid="2762241247228983754">"Түс"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Портреттік"</item>
     <item msgid="3199660090246166812">"Ландшафт"</item>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 63d710a..9bc3362 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"ទំហំ​​ក្រដាស"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"ទំហំ​ក្រដាស៖"</string>
     <string name="label_color" msgid="1108690305218188969">"ពណ៌"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"ទិស"</string>
     <string name="label_pages" msgid="7768589729282182230">"ទំព័រ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ទាំងអស់"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"ស &amp; ខ្មៅ"</item>
     <item msgid="2762241247228983754">"ពណ៌"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"គ្មាន"</item>
+    <item msgid="7296563835355641719">"គែម​វែង"</item>
+    <item msgid="79513688117503758">"គែម​ខ្លី"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"បញ្ឈរ"</item>
     <item msgid="3199660090246166812">"ផ្ដេក"</item>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index 3950866..61065e0 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"ಪೇಪರ್ ಗಾತ್ರ"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"ಪೇಪರ್ ಗಾತ್ರ:"</string>
     <string name="label_color" msgid="1108690305218188969">"ಬಣ್ಣ"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"ಓರಿಯಂಟೇಶನ್"</string>
     <string name="label_pages" msgid="7768589729282182230">"ಪುಟಗಳು"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ಎಲ್ಲಾ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"ಕಪ್ಪು &amp; ಬಿಳುಪು"</item>
     <item msgid="2762241247228983754">"ಬಣ್ಣ"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"ಪೋಟ್ರೇಟ್"</item>
     <item msgid="3199660090246166812">"ಲ್ಯಾಂಡ್‌ಸ್ಕೇಪ್"</item>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index f1a4869..448896c 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"용지 크기"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"용지 크기:"</string>
     <string name="label_color" msgid="1108690305218188969">"색상"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"방향"</string>
     <string name="label_pages" msgid="7768589729282182230">"페이지"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>페이지 모두"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"흑백"</item>
     <item msgid="2762241247228983754">"컬러"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"없음"</item>
+    <item msgid="7296563835355641719">"옆으로 넘김"</item>
+    <item msgid="79513688117503758">"위로 넘김"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"세로"</item>
     <item msgid="3199660090246166812">"가로"</item>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index 602f6605..64bd585 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Барактын өлчөмү"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Барактын өлчөмү:"</string>
     <string name="label_color" msgid="1108690305218188969">"Түс"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Багыттоо"</string>
     <string name="label_pages" msgid="7768589729282182230">"Баракчалар"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Бардыгы <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Кара-ак"</item>
     <item msgid="2762241247228983754">"Түстүү"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Тикесинен"</item>
     <item msgid="3199660090246166812">"Туурасынан"</item>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 3a3f6bb..9bd4d83 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"​ຂະ​ໜາດ​ເຈ້ຍ"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"​ຂະ​ໜາດ​ເຈ້ຍ:"</string>
     <string name="label_color" msgid="1108690305218188969">"ສີ"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"ລວງ"</string>
     <string name="label_pages" msgid="7768589729282182230">"ໜ້າ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ທັງ​ໝົດ <xliff:g id="PAGE_COUNT">%1$s</xliff:g> ໜ້າ"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"ຂາວດຳ"</item>
     <item msgid="2762241247228983754">"ສີ"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"ບໍ່ມີ"</item>
+    <item msgid="7296563835355641719">"ຂອບຍາວ"</item>
+    <item msgid="79513688117503758">"ຂອບສັ້ນ"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"ລວງຕັ້ງ"</item>
     <item msgid="3199660090246166812">"ລວງນອນ"</item>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index 6262a15..1116f6d 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Popieriaus dydis"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Popieriaus dydis:"</string>
     <string name="label_color" msgid="1108690305218188969">"Spalva"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientacija"</string>
     <string name="label_pages" msgid="7768589729282182230">"Puslapiai"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Visi <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Nespalvotas"</item>
     <item msgid="2762241247228983754">"Spalva"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nėra"</item>
+    <item msgid="7296563835355641719">"Ilgasis kraštas"</item>
+    <item msgid="79513688117503758">"Trumpasis kraštas"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Stačias"</item>
     <item msgid="3199660090246166812">"Gulsčias"</item>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 3a60ee5..d079ea9 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papīra izmērs"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papīra izmērs:"</string>
     <string name="label_color" msgid="1108690305218188969">"Krāsa"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Virziens"</string>
     <string name="label_pages" msgid="7768589729282182230">"Lapas"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Visas <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Melnbalts"</item>
     <item msgid="2762241247228983754">"Krāsa"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nav"</item>
+    <item msgid="7296563835355641719">"Garā mala"</item>
+    <item msgid="79513688117503758">"Īsā mala"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portrets"</item>
     <item msgid="3199660090246166812">"Ainava"</item>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index 91b5763..fec4841 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Големина на хартија"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Големина на хартија:"</string>
     <string name="label_color" msgid="1108690305218188969">"Боја"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Ориентација"</string>
     <string name="label_pages" msgid="7768589729282182230">"Страници"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Сите <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Црно-бела"</item>
     <item msgid="2762241247228983754">"Во боја"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Портрет"</item>
     <item msgid="3199660090246166812">"Пејзаж"</item>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index a06ca7d..743827f 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"പേപ്പർ വലുപ്പം"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"പേപ്പർ വലുപ്പം:"</string>
     <string name="label_color" msgid="1108690305218188969">"നിറം"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"ഓറിയന്‍റേഷന്‍‌"</string>
     <string name="label_pages" msgid="7768589729282182230">"പേജുകൾ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"എല്ലാ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"കറുപ്പ് &amp; വെള്ള"</item>
     <item msgid="2762241247228983754">"നിറം"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"പോർട്രെയ്‌റ്റ്"</item>
     <item msgid="3199660090246166812">"ലാൻഡ്‌സ്‌കേപ്പ്"</item>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index 022adda..8d0604a 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Цаасны хэмжээ"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Цаасны хэмжээ:"</string>
     <string name="label_color" msgid="1108690305218188969">"Өнгө"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Чиглэл"</string>
     <string name="label_pages" msgid="7768589729282182230">"Хуудас"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Нийт <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Хар &amp; Цагаан"</item>
     <item msgid="2762241247228983754">"Өнгө"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Хоосон"</item>
+    <item msgid="7296563835355641719">"Урт ирмэг"</item>
+    <item msgid="79513688117503758">"Богино ирмэг"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Босоо"</item>
     <item msgid="3199660090246166812">"Хэвтээ"</item>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index 1fade66..9036e0e 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"कागद आकार"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"कागद आकार:"</string>
     <string name="label_color" msgid="1108690305218188969">"रंग"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"अभिमुखता"</string>
     <string name="label_pages" msgid="7768589729282182230">"पृष्ठे"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"सर्व <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"कृष्‍ण धवल"</item>
     <item msgid="2762241247228983754">"रंग"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"पोट्रेट"</item>
     <item msgid="3199660090246166812">"भूदृश्य"</item>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index a392b76..0c7ecfb 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Saiz kertas"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Saiz kertas:"</string>
     <string name="label_color" msgid="1108690305218188969">"Warna"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
     <string name="label_pages" msgid="7768589729282182230">"Halaman"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Semua <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Hitam &amp; Putih"</item>
     <item msgid="2762241247228983754">"Warna"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Tiada"</item>
+    <item msgid="7296563835355641719">"Sisi panjang"</item>
+    <item msgid="79513688117503758">"Sisi pendek"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Potret"</item>
     <item msgid="3199660090246166812">"Landskap"</item>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index d6eb380..bbf2de4 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"စက္ကူ  ဆိုက်"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"စက္ကူ  ဆိုက်:"</string>
     <string name="label_color" msgid="1108690305218188969">"ရောင်စုံ"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"အနေအထား"</string>
     <string name="label_pages" msgid="7768589729282182230">"စာမျက်နှာများ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"အားလုံး <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"အဖြူ အမည်း"</item>
     <item msgid="2762241247228983754">"ရောင်စုံ"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"ထောင်လိုက်"</item>
     <item msgid="3199660090246166812">"အလျားလိုက်"</item>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index bf11068..1df90a9 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papirstørrelse"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papirstørrelse:"</string>
     <string name="label_color" msgid="1108690305218188969">"Farge"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Retning"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sider"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Svart og hvitt"</item>
     <item msgid="2762241247228983754">"Farge"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ingen"</item>
+    <item msgid="7296563835355641719">"Langsiden"</item>
+    <item msgid="79513688117503758">"Kortsiden"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Stående"</item>
     <item msgid="3199660090246166812">"Liggende"</item>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index eb97530..c2ecc3b 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"कागजको आकार"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"कागजको आकार:"</string>
     <string name="label_color" msgid="1108690305218188969">"रङ्ग"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"अभिमुखिकरण"</string>
     <string name="label_pages" msgid="7768589729282182230">"पृष्ठहरू"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"सबै <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"कालो &amp; सेतो"</item>
     <item msgid="2762241247228983754">"रङ्ग"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"कुनै पनि होइन"</item>
+    <item msgid="7296563835355641719">"लामो किनारा"</item>
+    <item msgid="79513688117503758">"छोटो किनारा"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"पोट्रेट"</item>
     <item msgid="3199660090246166812">"परिदृश्य"</item>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 5ea52a0..2a6c4c2 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Papierformaat"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Papierformaat:"</string>
     <string name="label_color" msgid="1108690305218188969">"Kleur"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Stand"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pagina\'s"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Zwart-wit"</item>
     <item msgid="2762241247228983754">"Kleur"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Geen"</item>
+    <item msgid="7296563835355641719">"Lange zijde"</item>
+    <item msgid="79513688117503758">"Korte zijde"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portret"</item>
     <item msgid="3199660090246166812">"Landschap"</item>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 609e6e9..a74a890 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Rozmiar papieru"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Rozmiar papieru:"</string>
     <string name="label_color" msgid="1108690305218188969">"Kolor"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientacja"</string>
     <string name="label_pages" msgid="7768589729282182230">"Strony"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Wszystkie <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Czarno-białe"</item>
     <item msgid="2762241247228983754">"Kolor"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Brak"</item>
+    <item msgid="7296563835355641719">"Długa krawędź"</item>
+    <item msgid="79513688117503758">"Krótka krawędź"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Pionowa"</item>
     <item msgid="3199660090246166812">"Pozioma"</item>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 7b47f4c..10b32ca 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Tamanho do papel"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Tamanho do papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Cor"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas as <xliff:g id="PAGE_COUNT">%1$s</xliff:g> páginas"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Preto e branco"</item>
     <item msgid="2762241247228983754">"Cor"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nenhum"</item>
+    <item msgid="7296563835355641719">"Limite grande"</item>
+    <item msgid="79513688117503758">"Limite curto"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Vertical"</item>
     <item msgid="3199660090246166812">"Horizontal"</item>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 3038a7f..eb1d9a0 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Tamanho do papel"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Tamanho do papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Cor"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas as <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Preto e branco"</item>
     <item msgid="2762241247228983754">"Cor"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Nenhum"</item>
+    <item msgid="7296563835355641719">"Borda longa"</item>
+    <item msgid="79513688117503758">"Borda curta"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Retrato"</item>
     <item msgid="3199660090246166812">"Paisagem"</item>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 1446a53..15ccb7d 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Formatul hârtiei"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Formatul hârtiei:"</string>
     <string name="label_color" msgid="1108690305218188969">"Color"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientare"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pagini"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Toate cele <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Alb-negru"</item>
     <item msgid="2762241247228983754">"Color"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Fără"</item>
+    <item msgid="7296563835355641719">"Latura lungă"</item>
+    <item msgid="79513688117503758">"Latura scurtă"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portret"</item>
     <item msgid="3199660090246166812">"Peisaj"</item>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index c2a19bb..f2d5bef 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Размер бумаги"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Размер бумаги:"</string>
     <string name="label_color" msgid="1108690305218188969">"Печать"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
     <string name="label_pages" msgid="7768589729282182230">"Страницы"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Все <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Черно-белая"</item>
     <item msgid="2762241247228983754">"Цветная"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Нет"</item>
+    <item msgid="7296563835355641719">"Длинный край"</item>
+    <item msgid="79513688117503758">"Короткий край"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Книга"</item>
     <item msgid="3199660090246166812">"Альбом"</item>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 386ce8d..f1b40c6 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"කඩදාසියේ ප්‍රමාණය"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"කඩදාසියේ ප්‍රමාණය:"</string>
     <string name="label_color" msgid="1108690305218188969">"වර්ණය"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"දිශානතිය"</string>
     <string name="label_pages" msgid="7768589729282182230">"පිටු"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"සියලුම <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"කළු සහ සුදු"</item>
     <item msgid="2762241247228983754">"වර්ණය"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"කිසිවක් නැත"</item>
+    <item msgid="7296563835355641719">"දිගු දාරය"</item>
+    <item msgid="79513688117503758">"කෙටි දාරය"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"ප්‍රතිමුර්ති"</item>
     <item msgid="3199660090246166812">"තිරස් දර්ශනය"</item>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 5be2034..fbf2bc7 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Veľkosť papiera"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Veľkosť papiera:"</string>
     <string name="label_color" msgid="1108690305218188969">"Farba"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientácia"</string>
     <string name="label_pages" msgid="7768589729282182230">"Strany"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Všetky: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Čiernobiele"</item>
     <item msgid="2762241247228983754">"Farba"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Žiadne"</item>
+    <item msgid="7296563835355641719">"Dlhý okraj"</item>
+    <item msgid="79513688117503758">"Krátky okraj"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Na výšku"</item>
     <item msgid="3199660090246166812">"Na šírku"</item>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index ee15103..a441d7c 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Velikost papirja"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Velikost papirja:"</string>
     <string name="label_color" msgid="1108690305218188969">"Barvno"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Postavitev"</string>
     <string name="label_pages" msgid="7768589729282182230">"Strani"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Vse (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Črno-belo"</item>
     <item msgid="2762241247228983754">"Barvno"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Brez"</item>
+    <item msgid="7296563835355641719">"Dolgi rob"</item>
+    <item msgid="79513688117503758">"Kratki rob"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Pokončno"</item>
     <item msgid="3199660090246166812">"Ležeče"</item>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 6ca94aa..622c84b 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Величина папира"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Величина папира:"</string>
     <string name="label_color" msgid="1108690305218188969">"Боја"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Положај"</string>
     <string name="label_pages" msgid="7768589729282182230">"Странице"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Све странице (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Црно-бело"</item>
     <item msgid="2762241247228983754">"Боја"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ништа"</item>
+    <item msgid="7296563835355641719">"Дуга ивица"</item>
+    <item msgid="79513688117503758">"Кратка ивица"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Усправно"</item>
     <item msgid="3199660090246166812">"Водоравно"</item>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index 4c439be..09ce6ee 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Pappersstorlek"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Pappersstorlek:"</string>
     <string name="label_color" msgid="1108690305218188969">"Färg"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Orientering"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sidor"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alla <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Svartvit"</item>
     <item msgid="2762241247228983754">"Färg"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Ingen"</item>
+    <item msgid="7296563835355641719">"Långsidan"</item>
+    <item msgid="79513688117503758">"Kortsidan"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Stående"</item>
     <item msgid="3199660090246166812">"Liggande"</item>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index e454704..a0497e6 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Ukubwa wa karatasi"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Ukubwa wa karatasi:"</string>
     <string name="label_color" msgid="1108690305218188969">"Rangi"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Mkao"</string>
     <string name="label_pages" msgid="7768589729282182230">"Kurasa"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Kurasa zote <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Nyeusi na Nyeupe"</item>
     <item msgid="2762241247228983754">"Rangi"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Hamna"</item>
+    <item msgid="7296563835355641719">"Ukingo mrefu"</item>
+    <item msgid="79513688117503758">"Ukingo mfupi"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Wima"</item>
     <item msgid="3199660090246166812">"Mlalo"</item>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index 0421bd6..a50470a 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"காகித அளவு"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"காகித அளவு:"</string>
     <string name="label_color" msgid="1108690305218188969">"வண்ணம்"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"திசையமைப்பு"</string>
     <string name="label_pages" msgid="7768589729282182230">"பக்கங்கள்"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"எல்லாம்: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"கருப்பு &amp; வெள்ளை"</item>
     <item msgid="2762241247228983754">"வண்ணம்"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"உறுவப்படம்"</item>
     <item msgid="3199660090246166812">"நிலத்தோற்றம்"</item>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index edb6e60..b35520d 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"కాగితపు పరిమాణం"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"కాగితపు పరిమాణం:"</string>
     <string name="label_color" msgid="1108690305218188969">"రంగు"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"దృగ్విన్యాసం"</string>
     <string name="label_pages" msgid="7768589729282182230">"పేజీలు"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"మొత్తం <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"నలుపు &amp; తెలుపు"</item>
     <item msgid="2762241247228983754">"రంగు"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"పోర్ట్రెయిట్"</item>
     <item msgid="3199660090246166812">"ల్యాండ్‌స్కేప్"</item>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index cfffa0b..9c8d55c 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"ขนาดของกระดาษ"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"ขนาดของกระดาษ:"</string>
     <string name="label_color" msgid="1108690305218188969">"สี"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"การวางแนว"</string>
     <string name="label_pages" msgid="7768589729282182230">"หน้า"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ทั้ง <xliff:g id="PAGE_COUNT">%1$s</xliff:g> หน้า"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"ขาวดำ"</item>
     <item msgid="2762241247228983754">"สี"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"ไม่มี"</item>
+    <item msgid="7296563835355641719">"ขอบยาว"</item>
+    <item msgid="79513688117503758">"ขอบสั้น"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"แนวตั้ง"</item>
     <item msgid="3199660090246166812">"แนวนอน"</item>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index dfb0450..9e4c7be 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Laki ng papel"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Laki ng papel:"</string>
     <string name="label_color" msgid="1108690305218188969">"Kulay"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Oryentasyon"</string>
     <string name="label_pages" msgid="7768589729282182230">"Mga Page"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Lahat ng <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Black &amp; White"</item>
     <item msgid="2762241247228983754">"Kulay"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Wala"</item>
+    <item msgid="7296563835355641719">"Long edge"</item>
+    <item msgid="79513688117503758">"Short edge"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Portrait"</item>
     <item msgid="3199660090246166812">"Landscape"</item>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index 50befba..902f4ce 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Kağıt boyutu"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Kağıt boyutu:"</string>
     <string name="label_color" msgid="1108690305218188969">"Renkli"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Sayfa yönü"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sayfa"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> sayfanın tamamı"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Siyah Beyaz"</item>
     <item msgid="2762241247228983754">"Renkli"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Yok"</item>
+    <item msgid="7296563835355641719">"Uzun kenar"</item>
+    <item msgid="79513688117503758">"Kısa kenar"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Dikey"</item>
     <item msgid="3199660090246166812">"Yatay"</item>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 8a924e6..71f9d61 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Розмір паперу"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Розмір паперу:"</string>
     <string name="label_color" msgid="1108690305218188969">"Колір"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Орієнтація"</string>
     <string name="label_pages" msgid="7768589729282182230">"Сторінки"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Усі <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Чорно-білий"</item>
     <item msgid="2762241247228983754">"Колір"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Немає"</item>
+    <item msgid="7296563835355641719">"Довгий край"</item>
+    <item msgid="79513688117503758">"Короткий край"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Книжкова"</item>
     <item msgid="3199660090246166812">"Альбомна"</item>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 722d027..2b32c30 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"کاغذ کا سائز"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"کاغذ کا سائز:"</string>
     <string name="label_color" msgid="1108690305218188969">"رنگ"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"سمت بندی"</string>
     <string name="label_pages" msgid="7768589729282182230">"صفحات"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"سبھی <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"سیاہ و سفید"</item>
     <item msgid="2762241247228983754">"رنگ"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"پورٹریٹ"</item>
     <item msgid="3199660090246166812">"لینڈ اسکیپ"</item>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index f62728f..57103d4 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Qog‘oz o‘lchami"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Qog‘oz o‘lchami:"</string>
     <string name="label_color" msgid="1108690305218188969">"Rang"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Joylashuv"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sahifalar"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Barchasi (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
@@ -77,6 +79,9 @@
     <item msgid="7602948745415174937">"Oq &amp; qora"</item>
     <item msgid="2762241247228983754">"Rang"</item>
   </string-array>
+    <!-- no translation found for duplex_mode_labels:0 (3882302912790928315) -->
+    <!-- no translation found for duplex_mode_labels:1 (7296563835355641719) -->
+    <!-- no translation found for duplex_mode_labels:2 (79513688117503758) -->
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Bo‘yiga"</item>
     <item msgid="3199660090246166812">"Eniga"</item>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index fa0d26e..3a9f8d4 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Khổ giấy"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Khổ giấy:"</string>
     <string name="label_color" msgid="1108690305218188969">"Màu"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Hướng"</string>
     <string name="label_pages" msgid="7768589729282182230">"Trang"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Tất cả <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Đen trắng"</item>
     <item msgid="2762241247228983754">"Màu"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Không có"</item>
+    <item msgid="7296563835355641719">"Cạnh dài"</item>
+    <item msgid="79513688117503758">"Cạnh ngắn"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Dọc"</item>
     <item msgid="3199660090246166812">"Ngang"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 77ecb21..80bab12 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"纸张尺寸"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"纸张尺寸:"</string>
     <string name="label_color" msgid="1108690305218188969">"颜色"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"页数"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"全部<xliff:g id="PAGE_COUNT">%1$s</xliff:g>页"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"黑白"</item>
     <item msgid="2762241247228983754">"彩色"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"无"</item>
+    <item msgid="7296563835355641719">"长边"</item>
+    <item msgid="79513688117503758">"短边"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"纵向"</item>
     <item msgid="3199660090246166812">"横向"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index d2fa629..bf6262c 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"紙張大小"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"紙張大小:"</string>
     <string name="label_color" msgid="1108690305218188969">"顏色"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"頁數"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"全部 <xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"黑白"</item>
     <item msgid="2762241247228983754">"彩色"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"無"</item>
+    <item msgid="7296563835355641719">"長邊"</item>
+    <item msgid="79513688117503758">"短邊"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"直向"</item>
     <item msgid="3199660090246166812">"橫向"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 3e26a5e..d822b41 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"紙張大小"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"紙張大小:"</string>
     <string name="label_color" msgid="1108690305218188969">"色彩"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"頁面"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"全部 <xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"黑白"</item>
     <item msgid="2762241247228983754">"彩色"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"無"</item>
+    <item msgid="7296563835355641719">"長邊"</item>
+    <item msgid="79513688117503758">"短邊"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"縱向"</item>
     <item msgid="3199660090246166812">"橫向"</item>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index f8a27bc..2b05cb0 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -24,6 +24,8 @@
     <string name="label_paper_size" msgid="908654383827777759">"Usayizi wekhasi"</string>
     <string name="label_paper_size_summary" msgid="5668204981332138168">"Usayizi wekhasi"</string>
     <string name="label_color" msgid="1108690305218188969">"Umbala"</string>
+    <!-- no translation found for label_duplex (1263181386446435253) -->
+    <skip />
     <string name="label_orientation" msgid="2853142581990496477">"Umumo"</string>
     <string name="label_pages" msgid="7768589729282182230">"Amakhasi"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Konke <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
@@ -77,6 +79,11 @@
     <item msgid="7602948745415174937">"Okumnyama nokumhlophe"</item>
     <item msgid="2762241247228983754">"Umbala"</item>
   </string-array>
+  <string-array name="duplex_mode_labels">
+    <item msgid="3882302912790928315">"Lutho"</item>
+    <item msgid="7296563835355641719">"Emaphethelweni amade"</item>
+    <item msgid="79513688117503758">"Emaphethelweni amafushane"</item>
+  </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"Ukuma ngobude"</item>
     <item msgid="3199660090246166812">"Ukwakheka kwezwe"</item>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index ab633ea..9d67ccc 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -40,6 +40,9 @@
     <!-- Label of the color mode widget. [CHAR LIMIT=20] -->
     <string name="label_color">Color</string>
 
+    <!-- Label of the duplex mode widget. [CHAR LIMIT=20] -->
+    <string name="label_duplex">Duplex</string>
+
     <!-- Label of the orientation widget. [CHAR LIMIT=20] -->
     <string name="label_orientation">Orientation</string>
 
@@ -188,12 +191,22 @@
 
     <!-- Color mode labels. -->
     <string-array name="color_mode_labels">
-        <!-- Color modelabel: Monochrome color scheme, e.g. one color is used. [CHAR LIMIT=20] -->
+        <!-- Color mode label: Monochrome color scheme, e.g. one color is used. [CHAR LIMIT=20] -->
         <item>Black &amp; White</item>
         <!-- Color mode label: Color color scheme, e.g. many colors are used. [CHAR LIMIT=20] -->
         <item>Color</item>
     </string-array>
 
+    <!-- Duplex mode labels. -->
+    <string-array name="duplex_mode_labels">
+        <!-- Duplex mode label: No duplex supported. [CHAR LIMIT=20] -->
+        <item>None</item>
+        <!-- Duplex mode label: Turn page sideways along the long edge like a book. [CHAR LIMIT=20] -->
+        <item>Long edge</item>
+        <!-- Duplex mode label: Turn page upwards along the short edge like a notepad. [CHAR LIMIT=20] -->
+        <item>Short edge</item>
+    </string-array>
+
     <!-- Orientation labels. -->
     <string-array name="orientation_labels">
         <!-- Orientation label: Portrait page orientation. [CHAR LIMIT=30] -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index 2cc5e04..377d2d5 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -695,6 +695,7 @@
         private static final String TAG_MARGINS = "margins";
 
         private static final String ATTR_COLOR_MODE = "colorMode";
+        private static final String ATTR_DUPLEX_MODE = "duplexMode";
 
         private static final String ATTR_LOCAL_ID = "localId";
         private static final String ATTR_SERVICE_NAME = "serviceName";
@@ -823,6 +824,10 @@
                         serializer.attribute(null, ATTR_COLOR_MODE,
                                 String.valueOf(colorMode));
 
+                        final int duplexMode = attributes.getDuplexMode();
+                        serializer.attribute(null, ATTR_DUPLEX_MODE,
+                                String.valueOf(duplexMode));
+
                         MediaSize mediaSize = attributes.getMediaSize();
                         if (mediaSize != null) {
                             serializer.startTag(null, TAG_MEDIA_SIZE);
@@ -1057,6 +1062,12 @@
                 String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
                 builder.setColorMode(Integer.parseInt(colorMode));
 
+                String duplexMode = parser.getAttributeValue(null, ATTR_DUPLEX_MODE);
+                // Duplex mode was added later, so null check is needed.
+                if (duplexMode != null) {
+                    builder.setDuplexMode(Integer.parseInt(duplexMode));
+                }
+
                 parser.next();
 
                 skipEmptyTextTags(parser);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index f3a5c95..4ba04e5 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -184,6 +184,9 @@
     private Spinner mColorModeSpinner;
     private ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
 
+    private Spinner mDuplexModeSpinner;
+    private ArrayAdapter<SpinnerItem<Integer>> mDuplexModeSpinnerAdapter;
+
     private Spinner mOrientationSpinner;
     private ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
 
@@ -767,6 +770,21 @@
                     }
                 }
             }
+
+            // Take the duplex mode only if the current printer supports it.
+            final int currDuplexMode = currAttributes.getDuplexMode();
+            final int newDuplexMode = newAttributes.getDuplexMode();
+            if (currDuplexMode != newDuplexMode) {
+                final int duplexModeCount = mDuplexModeSpinner.getCount();
+                for (int i = 0; i < duplexModeCount; i++) {
+                    final int supportedDuplexMode = mDuplexModeSpinnerAdapter.getItem(i).value;
+                    if (supportedDuplexMode == newDuplexMode) {
+                        currAttributes.setDuplexMode(newDuplexMode);
+                        mDuplexModeSpinner.setSelection(i);
+                        break;
+                    }
+                }
+            }
         }
 
         // Handle selected page changes making sure they are in the doc.
@@ -985,6 +1003,12 @@
             attributes.setColorMode(defaults.getColorMode());
         }
 
+        // Duplex mode.
+        final int duplexMode = attributes.getDuplexMode();
+        if ((capabilities.getDuplexModes() & duplexMode) == 0) {
+            attributes.setDuplexMode(defaults.getDuplexMode());
+        }
+
         // Resolution
         Resolution resolution = attributes.getResolution();
         if (resolution == null || !capabilities.getResolutions().contains(resolution)) {
@@ -1111,6 +1135,13 @@
         mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
         mColorModeSpinner.setOnItemSelectedListener(itemSelectedListener);
 
+        // Duplex mode.
+        mDuplexModeSpinnerAdapter = new ArrayAdapter<>(
+                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
+        mDuplexModeSpinner = (Spinner) findViewById(R.id.duplex_spinner);
+        mDuplexModeSpinner.setAdapter(mDuplexModeSpinnerAdapter);
+        mDuplexModeSpinner.setOnItemSelectedListener(itemSelectedListener);
+
         // Orientation
         mOrientationSpinnerAdapter = new ArrayAdapter<>(
                 this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
@@ -1187,6 +1218,7 @@
             mCopiesEditText.setFocusable(false);
             mMediaSizeSpinner.setEnabled(false);
             mColorModeSpinner.setEnabled(false);
+            mDuplexModeSpinner.setEnabled(false);
             mOrientationSpinner.setEnabled(false);
             mRangeOptionsSpinner.setEnabled(false);
             mPageRangeEditText.setEnabled(false);
@@ -1202,6 +1234,7 @@
             mCopiesEditText.setFocusable(false);
             mMediaSizeSpinner.setEnabled(false);
             mColorModeSpinner.setEnabled(false);
+            mDuplexModeSpinner.setEnabled(false);
             mOrientationSpinner.setEnabled(false);
             mRangeOptionsSpinner.setEnabled(false);
             mPageRangeEditText.setEnabled(false);
@@ -1317,7 +1350,7 @@
                 final int colorMode = 1 << colorBitOffset;
                 if (colorMode == oldColorMode) {
                     // Update the index of the old selection.
-                    oldColorModeNewIndex = colorBitOffset;
+                    oldColorModeNewIndex = mColorModeSpinnerAdapter.getCount();
                 }
                 remainingColorModes &= ~colorMode;
                 mColorModeSpinnerAdapter.add(new SpinnerItem<>(colorMode,
@@ -1339,11 +1372,81 @@
                             mColorModeSpinner.setSelection(i);
                         }
                         attributes.setColorMode(selectedColorMode);
+                        break;
                     }
                 }
             }
         }
 
+        // Duplex mode.
+        mDuplexModeSpinner.setEnabled(true);
+        final int duplexModes = capabilities.getDuplexModes();
+
+        // If the duplex modes changed, we update the adapter and the spinner.
+        // Note that we use bit count +1 to account for the no duplex option.
+        boolean duplexModesChanged = false;
+        if (Integer.bitCount(duplexModes) != mDuplexModeSpinnerAdapter.getCount()) {
+            duplexModesChanged = true;
+        } else {
+            int remainingDuplexModes = duplexModes;
+            int adapterIndex = 0;
+            while (remainingDuplexModes != 0) {
+                final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
+                final int duplexMode = 1 << duplexBitOffset;
+                remainingDuplexModes &= ~duplexMode;
+                if (duplexMode != mDuplexModeSpinnerAdapter.getItem(adapterIndex).value) {
+                    duplexModesChanged = true;
+                    break;
+                }
+                adapterIndex++;
+            }
+        }
+        if (duplexModesChanged) {
+            // Remember the old duplex mode to try selecting it again. Also the fallback
+            // is no duplexing which is always the first item in the dropdown.
+            int oldDuplexModeNewIndex = AdapterView.INVALID_POSITION;
+            final int oldDuplexMode = attributes.getDuplexMode();
+
+            // Rebuild the adapter data.
+            mDuplexModeSpinnerAdapter.clear();
+            String[] duplexModeLabels = getResources().getStringArray(R.array.duplex_mode_labels);
+            int remainingDuplexModes = duplexModes;
+            while (remainingDuplexModes != 0) {
+                final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
+                final int duplexMode = 1 << duplexBitOffset;
+                if (duplexMode == oldDuplexMode) {
+                    // Update the index of the old selection.
+                    oldDuplexModeNewIndex = mDuplexModeSpinnerAdapter.getCount();
+                }
+                remainingDuplexModes &= ~duplexMode;
+                mDuplexModeSpinnerAdapter.add(new SpinnerItem<>(duplexMode,
+                        duplexModeLabels[duplexBitOffset]));
+            }
+
+            if (oldDuplexModeNewIndex != AdapterView.INVALID_POSITION) {
+                // Select the old duplex mode - nothing really changed.
+                if (mDuplexModeSpinner.getSelectedItemPosition() != oldDuplexModeNewIndex) {
+                    mDuplexModeSpinner.setSelection(oldDuplexModeNewIndex);
+                }
+            } else {
+                // Select the default.
+                final int selectedDuplexMode = defaultAttributes.getDuplexMode();
+                final int itemCount = mDuplexModeSpinnerAdapter.getCount();
+                for (int i = 0; i < itemCount; i++) {
+                    SpinnerItem<Integer> item = mDuplexModeSpinnerAdapter.getItem(i);
+                    if (selectedDuplexMode == item.value) {
+                        if (mDuplexModeSpinner.getSelectedItemPosition() != i) {
+                            mDuplexModeSpinner.setSelection(i);
+                        }
+                        attributes.setDuplexMode(selectedDuplexMode);
+                        break;
+                    }
+                }
+            }
+        }
+
+        mDuplexModeSpinner.setEnabled(mDuplexModeSpinnerAdapter.getCount() > 1);
+
         // Orientation
         mOrientationSpinner.setEnabled(true);
         MediaSize mediaSize = attributes.getMediaSize();
@@ -2173,6 +2276,9 @@
             } else if (spinner == mColorModeSpinner) {
                 SpinnerItem<Integer> colorModeItem = mColorModeSpinnerAdapter.getItem(position);
                 mPrintJob.getAttributes().setColorMode(colorModeItem.value);
+            } else if (spinner == mDuplexModeSpinner) {
+                SpinnerItem<Integer> duplexModeItem = mDuplexModeSpinnerAdapter.getItem(position);
+                mPrintJob.getAttributes().setDuplexMode(duplexModeItem.value);
             } else if (spinner == mOrientationSpinner) {
                 SpinnerItem<Integer> orientationItem = mOrientationSpinnerAdapter.getItem(position);
                 PrintAttributes attributes = mPrintJob.getAttributes();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
index feb0316..6a6f1d3 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
@@ -48,16 +48,19 @@
     }
 
     @Override
+    public CharSequence getAccessibilityClassName() {
+        return CompoundButton.class.getName();
+    }
+
+    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
-        event.setClassName(CompoundButton.class.getName());
         event.setChecked(isSelected());
     }
 
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        info.setClassName(CompoundButton.class.getName());
         info.setSelected(false);
         info.setCheckable(true);
         info.setChecked(isSelected());
diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk
new file mode 100644
index 0000000..0245ed3
--- /dev/null
+++ b/packages/SettingsLib/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SettingsLib
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/core/res/res/color/btn_material_accent.xml b/packages/SettingsLib/AndroidManifest.xml
similarity index 64%
copy from core/res/res/color/btn_material_accent.xml
copy to packages/SettingsLib/AndroidManifest.xml
index 71469b6..eacafd5 100644
--- a/core/res/res/color/btn_material_accent.xml
+++ b/packages/SettingsLib/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+     Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,9 +15,6 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false"
-          android:alpha="?attr/disabledAlpha"
-          android:color="@color/button_material_dark" />
-    <item android:color="?attr/colorAccent" />
-</selector>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.settingslib">
+</manifest>
diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk
new file mode 100644
index 0000000..b017047
--- /dev/null
+++ b/packages/SettingsLib/common.mk
@@ -0,0 +1,18 @@
+#
+# Include this make file to build your application against this module.
+#
+# Make sure to include it after you've set all your desired LOCAL variables.
+# Note that you must explicitly set your LOCAL_RESOURCE_DIR before including
+# this file.
+#
+# For example:
+#
+#   LOCAL_RESOURCE_DIR := \
+#        $(LOCAL_PATH)/res
+#
+#   include frameworks/base/packages/SettingsLib/common.mk
+#
+
+LOCAL_RESOURCE_DIR += $(call my-dir)/res
+LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.android.settingslib
+LOCAL_STATIC_JAVA_LIBRARIES += SettingsLib
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
new file mode 100644
index 0000000..a52ed69
--- /dev/null
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Wi-Fi settings -->
+
+    <!-- Match this with the order of NetworkInfo.DetailedState. --> <skip />
+    <!-- Wi-Fi settings. The status messages when the network is unknown. -->
+    <string-array name="wifi_status">
+        <!-- Status message of Wi-Fi when it is idle. -->
+        <item></item>
+        <!-- Status message of Wi-Fi when it is scanning. -->
+        <item>Scanning\u2026</item>
+        <!-- Status message of Wi-Fi when it is connecting. -->
+        <item>Connecting\u2026</item>
+        <!-- Status message of Wi-Fi when it is authenticating. -->
+        <item>Authenticating\u2026</item>
+        <!-- Status message of Wi-Fi when it is obtaining IP address. -->
+        <item>Obtaining IP address\u2026</item>
+        <!-- Status message of Wi-Fi when it is connected. -->
+        <item>Connected</item>
+        <!-- Status message of Wi-Fi when it is suspended. -->
+        <item>Suspended</item>
+        <!-- Status message of Wi-Fi when it is disconnecting. -->
+        <item>Disconnecting\u2026</item>
+        <!-- Status message of Wi-Fi when it is disconnected. -->
+        <item>Disconnected</item>
+        <!-- Status message of Wi-Fi when it is a failure. -->
+        <item>Unsuccessful</item>
+        <!-- Status message of Wi-Fi when it is blocked. -->
+        <item>Blocked</item>
+        <!-- Status message of Wi-Fi when connectiong is being verified. -->
+        <item>Temporarily avoiding poor connection</item>
+    </string-array>
+
+    <!-- Match this with the order of NetworkInfo.DetailedState. --> <skip />
+    <!-- Wi-Fi settings. The status messages when the network is known. -->
+    <string-array name="wifi_status_with_ssid">
+        <!-- Status message of Wi-Fi when it is idle. -->
+        <item></item>
+        <!-- Status message of Wi-Fi when it is scanning. -->
+        <item>Scanning\u2026</item>
+        <!-- Status message of Wi-Fi when it is connecting to a network. -->
+        <item>Connecting to <xliff:g id="network_name">%1$s</xliff:g>\u2026</item>
+        <!-- Status message of Wi-Fi when it is authenticating with a network. -->
+        <item>Authenticating with <xliff:g id="network_name">%1$s</xliff:g>\u2026</item>
+        <!-- Status message of Wi-Fi when it is obtaining IP address from a network. -->
+        <item>Obtaining IP address from <xliff:g id="network_name">%1$s</xliff:g>\u2026</item>
+        <!-- Status message of Wi-Fi when it is connected to a network. -->
+        <item>Connected to <xliff:g id="network_name">%1$s</xliff:g></item>
+        <!-- Status message of Wi-Fi when it is suspended. -->
+        <item>Suspended</item>
+        <!-- Status message of Wi-Fi when it is disconnecting from a network. -->
+        <item>Disconnecting from <xliff:g id="network_name">%1$s</xliff:g>\u2026</item>
+        <!-- Status message of Wi-Fi when it is disconnected. -->
+        <item>Disconnected</item>
+        <!-- Status message of Wi-Fi when it is a failure. -->
+        <item>Unsuccessful</item>
+        <!-- Status message of Wi-Fi when it is blocked. -->
+        <item>Blocked</item>
+        <!-- Status message of Wi-Fi when connectiong is being verified. -->
+        <item>Temporarily avoiding poor connection</item>
+    </string-array>
+</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
new file mode 100644
index 0000000..f055a2c
--- /dev/null
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Toast message when Wi-Fi cannot scan for networks -->
+    <string name="wifi_fail_to_scan">Can\'t scan for networks</string>
+    <!-- Do not translate.  Concise terminology for wifi with WEP security -->
+    <string name="wifi_security_short_wep">WEP</string>
+    <!-- Do not translate.  Concise terminology for wifi with WPA security -->
+    <string name="wifi_security_short_wpa">WPA</string>
+    <!-- Do not translate.  Concise terminology for wifi with WPA2 security -->
+    <string name="wifi_security_short_wpa2">WPA2</string>
+    <!-- Do not translate.  Concise terminology for wifi with both WPA/WPA2 security -->
+    <string name="wifi_security_short_wpa_wpa2">WPA/WPA2</string>
+    <!-- Do not translate.  Concise terminology for wifi with unknown PSK type -->
+    <string name="wifi_security_short_psk_generic">@string/wifi_security_short_wpa_wpa2</string>
+    <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP security -->
+    <string name="wifi_security_short_eap">802.1x</string>
+
+    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. -->
+    <string name="wifi_security_none">None</string>
+
+    <!-- Do not translate.  Terminology for wifi with WEP security -->
+    <string name="wifi_security_wep">WEP</string>
+    <!-- Do not translate.  Terminology for wifi with WPA security -->
+    <string name="wifi_security_wpa">WPA PSK</string>
+    <!-- Do not translate.  Terminology for wifi with WPA2 security -->
+    <string name="wifi_security_wpa2">WPA2 PSK</string>
+    <!-- Do not translate.  Terminology for wifi with both WPA/WPA2 security, or unknown -->
+    <string name="wifi_security_wpa_wpa2">WPA/WPA2 PSK</string>
+    <!-- Do not translate.  Terminology for wifi with unknown PSK type -->
+    <string name="wifi_security_psk_generic">@string/wifi_security_wpa_wpa2</string>
+    <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP security -->
+    <string name="wifi_security_eap">802.1x EAP</string>
+
+    <!-- Summary for the remembered network. -->
+    <string name="wifi_remembered">Saved</string>
+    <!-- Status for networks disabled for unknown reason -->
+    <string name="wifi_disabled_generic">Disabled</string>
+    <!-- Status for networked disabled from a DNS or DHCP failure -->
+    <string name="wifi_disabled_network_failure">IP Configuration Failure</string>
+    <!-- Status for networked disabled from a wifi association failure -->
+    <string name="wifi_disabled_wifi_failure">WiFi Connection Failure</string>
+    <!-- Status for networks disabled from authentication failure (wrong password
+         or certificate). -->
+    <string name="wifi_disabled_password_failure">Authentication problem</string>
+    <!-- Summary for the remembered network but currently not in range. -->
+    <string name="wifi_not_in_range">Not in range</string>
+    <!-- Summary for the remembered network but no internet connection was detected. -->
+    <string name="wifi_no_internet">No Internet Access Detected, won\'t automatically reconnect.</string>
+
+    <!-- Status message of Wi-Fi when it is connected by a Wi-Fi assistant application. [CHAR LIMIT=NONE] -->
+    <string name="connected_via_wfa">Connected via Wi\u2011Fi assistant</string>
+</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/WirelessUtils.java b/packages/SettingsLib/src/com/android/settingslib/WirelessUtils.java
new file mode 100644
index 0000000..0346a77
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/WirelessUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.content.Context;
+import android.provider.Settings;
+
+public class WirelessUtils {
+
+    public static boolean isRadioAllowed(Context context, String type) {
+        if (!isAirplaneModeOn(context)) {
+            return true;
+        }
+        String toggleable = Settings.Global.getString(context.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        return toggleable != null && toggleable.contains(type);
+    }
+
+    public static boolean isAirplaneModeOn(Context context) {
+        return Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
new file mode 100644
index 0000000..e8ab220
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -0,0 +1,739 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.wifi;
+
+import android.content.Context;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkInfo.State;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.LruCache;
+
+import com.android.settingslib.R;
+
+import java.util.Map;
+
+
+public class AccessPoint implements Comparable<AccessPoint> {
+    static final String TAG = "SettingsLib.AccessPoint";
+
+    /**
+     * Lower bound on the 2.4 GHz (802.11b/g/n) WLAN channels
+     */
+    public static final int LOWER_FREQ_24GHZ = 2400;
+
+    /**
+     * Upper bound on the 2.4 GHz (802.11b/g/n) WLAN channels
+     */
+    public static final int HIGHER_FREQ_24GHZ = 2500;
+
+    /**
+     * Lower bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
+     */
+    public static final int LOWER_FREQ_5GHZ = 4900;
+
+    /**
+     * Upper bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels
+     */
+    public static final int HIGHER_FREQ_5GHZ = 5900;
+
+
+    /**
+     * Experimental: we should be able to show the user the list of BSSIDs and bands
+     *  for that SSID.
+     *  For now this data is used only with Verbose Logging so as to show the band and number
+     *  of BSSIDs on which that network is seen.
+     */
+    public LruCache<String, ScanResult> mScanResultCache;
+    private static final String KEY_NETWORKINFO = "key_networkinfo";
+    private static final String KEY_WIFIINFO = "key_wifiinfo";
+    private static final String KEY_SCANRESULT = "key_scanresult";
+    private static final String KEY_CONFIG = "key_config";
+
+    /**
+     * These values are matched in string arrays -- changes must be kept in sync
+     */
+    public static final int SECURITY_NONE = 0;
+    public static final int SECURITY_WEP = 1;
+    public static final int SECURITY_PSK = 2;
+    public static final int SECURITY_EAP = 3;
+
+    private static final int PSK_UNKNOWN = 0;
+    private static final int PSK_WPA = 1;
+    private static final int PSK_WPA2 = 2;
+    private static final int PSK_WPA_WPA2 = 3;
+
+    private static final int VISIBILITY_OUTDATED_AGE_IN_MILLI = 20000;
+    private final Context mContext;
+
+    private String ssid;
+    private int security;
+    private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
+
+    private int pskType = PSK_UNKNOWN;
+
+    private WifiConfiguration mConfig;
+    private ScanResult mScanResult;
+
+    private int mRssi = Integer.MAX_VALUE;
+    private long mSeen = 0;
+
+    private WifiInfo mInfo;
+    private NetworkInfo mNetworkInfo;
+    private AccessPointListener mAccessPointListener;
+
+    private Object mTag;
+
+    public AccessPoint(Context context, Bundle savedState) {
+        mContext = context;
+        mConfig = savedState.getParcelable(KEY_CONFIG);
+        if (mConfig != null) {
+            loadConfig(mConfig);
+        }
+        mScanResult = (ScanResult) savedState.getParcelable(KEY_SCANRESULT);
+        if (mScanResult != null) {
+            loadResult(mScanResult);
+        }
+        mInfo = (WifiInfo) savedState.getParcelable(KEY_WIFIINFO);
+        if (savedState.containsKey(KEY_NETWORKINFO)) {
+            mNetworkInfo = savedState.getParcelable(KEY_NETWORKINFO);
+        }
+        update(mInfo, mNetworkInfo);
+    }
+
+    AccessPoint(Context context, ScanResult result) {
+        mContext = context;
+        loadResult(result);
+    }
+
+    AccessPoint(Context context, WifiConfiguration config) {
+        mContext = context;
+        loadConfig(config);
+    }
+
+    @Override
+    public int compareTo(AccessPoint other) {
+        // Active one goes first.
+        if (isActive() && !other.isActive()) return -1;
+        if (!isActive() && other.isActive()) return 1;
+
+        // Reachable one goes before unreachable one.
+        if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
+        if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
+
+        // Configured one goes before unconfigured one.
+        if (networkId != WifiConfiguration.INVALID_NETWORK_ID
+                && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
+        if (networkId == WifiConfiguration.INVALID_NETWORK_ID
+                && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
+
+        // Sort by signal strength.
+        int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi);
+        if (difference != 0) {
+            return difference;
+        }
+        // Sort by ssid.
+        return ssid.compareToIgnoreCase(other.ssid);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof AccessPoint)) return false;
+        return (this.compareTo((AccessPoint) other) == 0);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 0;
+        if (mInfo != null) result += 13 * mInfo.hashCode();
+        result += 19 * mRssi;
+        result += 23 * networkId;
+        result += 29 * ssid.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder().append("AccessPoint(")
+                .append(ssid);
+        if (isSaved()) {
+            builder.append(',').append("saved");
+        }
+        if (isActive()) {
+            builder.append(',').append("active");
+        }
+        if (isEphemeral()) {
+            builder.append(',').append("ephemeral");
+        }
+        if (isConnectable()) {
+            builder.append(',').append("connectable");
+        }
+        if (security != SECURITY_NONE) {
+            builder.append(',').append(securityToString(security, pskType));
+        }
+        return builder.append(')').toString();
+    }
+
+    public boolean matches(ScanResult result) {
+        return ssid.equals(result.SSID) && security == getSecurity(result);
+    }
+
+    public boolean matches(WifiConfiguration config) {
+        return ssid.equals(removeDoubleQuotes(config.SSID)) && security == getSecurity(config);
+    }
+
+    public WifiConfiguration getConfig() {
+        return mConfig;
+    }
+
+    public void clearConfig() {
+        mConfig = null;
+        networkId = WifiConfiguration.INVALID_NETWORK_ID;
+    }
+
+    public WifiInfo getInfo() {
+        return mInfo;
+    }
+
+    public int getLevel() {
+        if (mRssi == Integer.MAX_VALUE) {
+            return -1;
+        }
+        return WifiManager.calculateSignalLevel(mRssi, 4);
+    }
+
+    public NetworkInfo getNetworkInfo() {
+        return mNetworkInfo;
+    }
+
+    public int getSecurity() {
+        return security;
+    }
+
+    public String getSecurityString(boolean concise) {
+        Context context = mContext;
+        switch(security) {
+            case SECURITY_EAP:
+                return concise ? context.getString(R.string.wifi_security_short_eap) :
+                    context.getString(R.string.wifi_security_eap);
+            case SECURITY_PSK:
+                switch (pskType) {
+                    case PSK_WPA:
+                        return concise ? context.getString(R.string.wifi_security_short_wpa) :
+                            context.getString(R.string.wifi_security_wpa);
+                    case PSK_WPA2:
+                        return concise ? context.getString(R.string.wifi_security_short_wpa2) :
+                            context.getString(R.string.wifi_security_wpa2);
+                    case PSK_WPA_WPA2:
+                        return concise ? context.getString(R.string.wifi_security_short_wpa_wpa2) :
+                            context.getString(R.string.wifi_security_wpa_wpa2);
+                    case PSK_UNKNOWN:
+                    default:
+                        return concise ? context.getString(R.string.wifi_security_short_psk_generic)
+                                : context.getString(R.string.wifi_security_psk_generic);
+                }
+            case SECURITY_WEP:
+                return concise ? context.getString(R.string.wifi_security_short_wep) :
+                    context.getString(R.string.wifi_security_wep);
+            case SECURITY_NONE:
+            default:
+                return concise ? "" : context.getString(R.string.wifi_security_none);
+        }
+    }
+
+    public String getSsid() {
+        return ssid;
+    }
+
+    public DetailedState getDetailedState() {
+        return mNetworkInfo != null ? mNetworkInfo.getDetailedState() : null;
+    }
+
+    public String getSummary() {
+        // Update to new summary
+        StringBuilder summary = new StringBuilder();
+
+        if (isActive()) { // This is the active connection
+            summary.append(getSummary(mContext, getDetailedState(),
+                    networkId == WifiConfiguration.INVALID_NETWORK_ID));
+        } else if (mConfig != null
+                && mConfig.hasNoInternetAccess()) {
+            summary.append(mContext.getString(R.string.wifi_no_internet));
+        } else if (mConfig != null && ((mConfig.status == WifiConfiguration.Status.DISABLED &&
+                mConfig.disableReason != WifiConfiguration.DISABLED_UNKNOWN_REASON)
+               || mConfig.autoJoinStatus
+                >= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE)) {
+            if (mConfig.autoJoinStatus
+                    >= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE) {
+                if (mConfig.disableReason == WifiConfiguration.DISABLED_DHCP_FAILURE) {
+                    summary.append(mContext.getString(R.string.wifi_disabled_network_failure));
+                } else if (mConfig.disableReason == WifiConfiguration.DISABLED_AUTH_FAILURE) {
+                    summary.append(mContext.getString(R.string.wifi_disabled_password_failure));
+                } else {
+                    summary.append(mContext.getString(R.string.wifi_disabled_wifi_failure));
+                }
+            } else {
+                switch (mConfig.disableReason) {
+                    case WifiConfiguration.DISABLED_AUTH_FAILURE:
+                        summary.append(mContext.getString(R.string.wifi_disabled_password_failure));
+                        break;
+                    case WifiConfiguration.DISABLED_DHCP_FAILURE:
+                    case WifiConfiguration.DISABLED_DNS_FAILURE:
+                        summary.append(mContext.getString(R.string.wifi_disabled_network_failure));
+                        break;
+                    case WifiConfiguration.DISABLED_UNKNOWN_REASON:
+                    case WifiConfiguration.DISABLED_ASSOCIATION_REJECT:
+                        summary.append(mContext.getString(R.string.wifi_disabled_generic));
+                        break;
+                }
+            }
+        } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
+            summary.append(mContext.getString(R.string.wifi_not_in_range));
+        } else { // In range, not disabled.
+            if (mConfig != null) { // Is saved network
+                summary.append(mContext.getString(R.string.wifi_remembered));
+            }
+        }
+
+        if (WifiTracker.sVerboseLogging > 0) {
+            // Add RSSI/band information for this config, what was seen up to 6 seconds ago
+            // verbose WiFi Logging is only turned on thru developers settings
+            if (mInfo != null && mNetworkInfo != null) { // This is the active connection
+                summary.append(" f=" + Integer.toString(mInfo.getFrequency()));
+            }
+            summary.append(" " + getVisibilityStatus());
+            if (mConfig != null && mConfig.autoJoinStatus > 0) {
+                summary.append(" (" + mConfig.autoJoinStatus);
+                if (mConfig.blackListTimestamp > 0) {
+                    long now = System.currentTimeMillis();
+                    long diff = (now - mConfig.blackListTimestamp)/1000;
+                    long sec = diff%60; //seconds
+                    long min = (diff/60)%60; //minutes
+                    long hour = (min/60)%60; //hours
+                    summary.append(", ");
+                    if (hour > 0) summary.append(Long.toString(hour) + "h ");
+                    summary.append( Long.toString(min) + "m ");
+                    summary.append( Long.toString(sec) + "s ");
+                }
+                summary.append(")");
+            }
+            if (mConfig != null && mConfig.numIpConfigFailures > 0) {
+                summary.append(" ipf=").append(mConfig.numIpConfigFailures);
+            }
+            if (mConfig != null && mConfig.numConnectionFailures > 0) {
+                summary.append(" cf=").append(mConfig.numConnectionFailures);
+            }
+            if (mConfig != null && mConfig.numAuthFailures > 0) {
+                summary.append(" authf=").append(mConfig.numAuthFailures);
+            }
+            if (mConfig != null && mConfig.numNoInternetAccessReports > 0) {
+                summary.append(" noInt=").append(mConfig.numNoInternetAccessReports);
+            }
+        }
+        return summary.toString();
+    }
+
+    /**
+     * Returns the visibility status of the WifiConfiguration.
+     *
+     * @return autojoin debugging information
+     * TODO: use a string formatter
+     * ["rssi 5Ghz", "num results on 5GHz" / "rssi 5Ghz", "num results on 5GHz"]
+     * For instance [-40,5/-30,2]
+     */
+    private String getVisibilityStatus() {
+        StringBuilder visibility = new StringBuilder();
+        StringBuilder scans24GHz = null;
+        StringBuilder scans5GHz = null;
+        String bssid = null;
+
+        long now = System.currentTimeMillis();
+
+        if (mInfo != null) {
+            bssid = mInfo.getBSSID();
+            if (bssid != null) {
+                visibility.append(" ").append(bssid);
+            }
+            visibility.append(" rssi=").append(mInfo.getRssi());
+            visibility.append(" ");
+            visibility.append(" score=").append(mInfo.score);
+            visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate));
+            visibility.append(String.format("%.1f,", mInfo.txRetriesRate));
+            visibility.append(String.format("%.1f ", mInfo.txBadRate));
+            visibility.append(String.format("rx=%.1f", mInfo.rxSuccessRate));
+        }
+
+        if (mScanResultCache != null) {
+            int rssi5 = WifiConfiguration.INVALID_RSSI;
+            int rssi24 = WifiConfiguration.INVALID_RSSI;
+            int num5 = 0;
+            int num24 = 0;
+            int numBlackListed = 0;
+            int n24 = 0; // Number scan results we included in the string
+            int n5 = 0; // Number scan results we included in the string
+            Map<String, ScanResult> list = mScanResultCache.snapshot();
+            // TODO: sort list by RSSI or age
+            for (ScanResult result : list.values()) {
+                if (result.seen == 0)
+                    continue;
+
+                if (result.autoJoinStatus != ScanResult.ENABLED) numBlackListed++;
+
+                if (result.frequency >= LOWER_FREQ_5GHZ
+                        && result.frequency <= HIGHER_FREQ_5GHZ) {
+                    // Strictly speaking: [4915, 5825]
+                    // number of known BSSID on 5GHz band
+                    num5 = num5 + 1;
+                } else if (result.frequency >= LOWER_FREQ_24GHZ
+                        && result.frequency <= HIGHER_FREQ_24GHZ) {
+                    // Strictly speaking: [2412, 2482]
+                    // number of known BSSID on 2.4Ghz band
+                    num24 = num24 + 1;
+                }
+
+                // Ignore results seen, older than 20 seconds
+                if (now - result.seen > VISIBILITY_OUTDATED_AGE_IN_MILLI) continue;
+
+                if (result.frequency >= LOWER_FREQ_5GHZ
+                        && result.frequency <= HIGHER_FREQ_5GHZ) {
+                    if (result.level > rssi5) {
+                        rssi5 = result.level;
+                    }
+                    if (n5 < 4) {
+                        if (scans5GHz == null) scans5GHz = new StringBuilder();
+                        scans5GHz.append(" \n{").append(result.BSSID);
+                        if (bssid != null && result.BSSID.equals(bssid)) scans5GHz.append("*");
+                        scans5GHz.append("=").append(result.frequency);
+                        scans5GHz.append(",").append(result.level);
+                        if (result.autoJoinStatus != 0) {
+                            scans5GHz.append(",st=").append(result.autoJoinStatus);
+                        }
+                        if (result.numIpConfigFailures != 0) {
+                            scans5GHz.append(",ipf=").append(result.numIpConfigFailures);
+                        }
+                        scans5GHz.append("}");
+                        n5++;
+                    }
+                } else if (result.frequency >= LOWER_FREQ_24GHZ
+                        && result.frequency <= HIGHER_FREQ_24GHZ) {
+                    if (result.level > rssi24) {
+                        rssi24 = result.level;
+                    }
+                    if (n24 < 4) {
+                        if (scans24GHz == null) scans24GHz = new StringBuilder();
+                        scans24GHz.append(" \n{").append(result.BSSID);
+                        if (bssid != null && result.BSSID.equals(bssid)) scans24GHz.append("*");
+                        scans24GHz.append("=").append(result.frequency);
+                        scans24GHz.append(",").append(result.level);
+                        if (result.autoJoinStatus != 0) {
+                            scans24GHz.append(",st=").append(result.autoJoinStatus);
+                        }
+                        if (result.numIpConfigFailures != 0) {
+                            scans24GHz.append(",ipf=").append(result.numIpConfigFailures);
+                        }
+                        scans24GHz.append("}");
+                        n24++;
+                    }
+                }
+            }
+            visibility.append(" [");
+            if (num24 > 0) {
+                visibility.append("(").append(num24).append(")");
+                if (n24 <= 4) {
+                    if (scans24GHz != null) {
+                        visibility.append(scans24GHz.toString());
+                    }
+                } else {
+                    visibility.append("max=").append(rssi24);
+                    if (scans24GHz != null) {
+                        visibility.append(",").append(scans24GHz.toString());
+                    }
+                }
+            }
+            visibility.append(";");
+            if (num5 > 0) {
+                visibility.append("(").append(num5).append(")");
+                if (n5 <= 4) {
+                    if (scans5GHz != null) {
+                        visibility.append(scans5GHz.toString());
+                    }
+                } else {
+                    visibility.append("max=").append(rssi5);
+                    if (scans5GHz != null) {
+                        visibility.append(",").append(scans5GHz.toString());
+                    }
+                }
+            }
+            if (numBlackListed > 0)
+                visibility.append("!").append(numBlackListed);
+            visibility.append("]");
+        } else {
+            if (mRssi != Integer.MAX_VALUE) {
+                visibility.append(" rssi=");
+                visibility.append(mRssi);
+                if (mScanResult != null) {
+                    visibility.append(", f=");
+                    visibility.append(mScanResult.frequency);
+                }
+            }
+        }
+
+        return visibility.toString();
+    }
+
+    /**
+     * Return whether this is the active connection.
+     * For ephemeral connections (networkId is invalid), this returns false if the network is
+     * disconnected.
+     */
+    public boolean isActive() {
+        return mNetworkInfo != null &&
+                (networkId != WifiConfiguration.INVALID_NETWORK_ID ||
+                 mNetworkInfo.getState() != State.DISCONNECTED);
+    }
+
+    public boolean isConnectable() {
+        return getLevel() != -1 && getDetailedState() == null;
+    }
+
+    public boolean isEphemeral() {
+        return !isSaved() && mNetworkInfo != null && mNetworkInfo.getState() != State.DISCONNECTED;
+    }
+
+    /** Return whether the given {@link WifiInfo} is for this access point. */
+    private boolean isInfoForThisAccessPoint(WifiInfo info) {
+        if (networkId != WifiConfiguration.INVALID_NETWORK_ID) {
+            return networkId == info.getNetworkId();
+        } else {
+            // Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID.
+            // (Note that we only do this if the WifiConfiguration explicitly equals INVALID).
+            // TODO: Handle hex string SSIDs.
+            return ssid.equals(removeDoubleQuotes(info.getSSID()));
+        }
+    }
+
+    public boolean isSaved() {
+        return networkId != WifiConfiguration.INVALID_NETWORK_ID;
+    }
+
+    public Object getTag() {
+        return mTag;
+    }
+
+    public void setTag(Object tag) {
+        mTag = tag;
+    }
+
+    /**
+     * Generate and save a default wifiConfiguration with common values.
+     * Can only be called for unsecured networks.
+     */
+    public void generateOpenNetworkConfig() {
+        if (security != SECURITY_NONE)
+            throw new IllegalStateException();
+        if (mConfig != null)
+            return;
+        mConfig = new WifiConfiguration();
+        mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
+        mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+    }
+
+    void loadConfig(WifiConfiguration config) {
+        ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
+        security = getSecurity(config);
+        networkId = config.networkId;
+        mConfig = config;
+    }
+
+    private void loadResult(ScanResult result) {
+        ssid = result.SSID;
+        security = getSecurity(result);
+        if (security == SECURITY_PSK)
+            pskType = getPskType(result);
+        mRssi = result.level;
+        mScanResult = result;
+        if (result.seen > mSeen) {
+            mSeen = result.seen;
+        }
+    }
+
+    public void saveWifiState(Bundle savedState) {
+        savedState.putParcelable(KEY_CONFIG, mConfig);
+        savedState.putParcelable(KEY_SCANRESULT, mScanResult);
+        savedState.putParcelable(KEY_WIFIINFO, mInfo);
+        if (mNetworkInfo != null) {
+            savedState.putParcelable(KEY_NETWORKINFO, mNetworkInfo);
+        }
+    }
+
+    public void setListener(AccessPointListener listener) {
+        mAccessPointListener = listener;
+    }
+
+    boolean update(ScanResult result) {
+        if (result.seen > mSeen) {
+            mSeen = result.seen;
+        }
+        if (WifiTracker.sVerboseLogging > 0) {
+            if (mScanResultCache == null) {
+                mScanResultCache = new LruCache<String, ScanResult>(32);
+            }
+            mScanResultCache.put(result.BSSID, result);
+        }
+
+        if (ssid.equals(result.SSID) && security == getSecurity(result)) {
+            if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) {
+                int oldLevel = getLevel();
+                mRssi = result.level;
+                if (getLevel() != oldLevel && mAccessPointListener != null) {
+                    mAccessPointListener.onLevelChanged(this);
+                }
+            }
+            // This flag only comes from scans, is not easily saved in config
+            if (security == SECURITY_PSK) {
+                pskType = getPskType(result);
+            }
+            mScanResult = result;
+            if (mAccessPointListener != null) {
+                mAccessPointListener.onAccessPointChanged(this);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    boolean update(WifiInfo info, NetworkInfo networkInfo) {
+        boolean reorder = false;
+        if (info != null && isInfoForThisAccessPoint(info)) {
+            reorder = (mInfo == null);
+            mRssi = info.getRssi();
+            mInfo = info;
+            mNetworkInfo = networkInfo;
+            if (mAccessPointListener != null) {
+                mAccessPointListener.onAccessPointChanged(this);
+            }
+        } else if (mInfo != null) {
+            reorder = true;
+            mInfo = null;
+            mNetworkInfo = null;
+            if (mAccessPointListener != null) {
+                mAccessPointListener.onAccessPointChanged(this);
+            }
+        }
+        return reorder;
+    }
+
+    public static String getSummary(Context context, String ssid, DetailedState state,
+            boolean isEphemeral) {
+        if (state == DetailedState.CONNECTED && isEphemeral && ssid == null) {
+            // Special case for connected + ephemeral networks.
+            return context.getString(R.string.connected_via_wfa);
+        }
+
+        String[] formats = context.getResources().getStringArray((ssid == null)
+                ? R.array.wifi_status : R.array.wifi_status_with_ssid);
+        int index = state.ordinal();
+
+        if (index >= formats.length || formats[index].length() == 0) {
+            return null;
+        }
+        return String.format(formats[index], ssid);
+    }
+
+    public static String getSummary(Context context, DetailedState state, boolean isEphemeral) {
+        return getSummary(context, null, state, isEphemeral);
+    }
+
+    public static String convertToQuotedString(String string) {
+        return "\"" + string + "\"";
+    }
+
+    private static int getPskType(ScanResult result) {
+        boolean wpa = result.capabilities.contains("WPA-PSK");
+        boolean wpa2 = result.capabilities.contains("WPA2-PSK");
+        if (wpa2 && wpa) {
+            return PSK_WPA_WPA2;
+        } else if (wpa2) {
+            return PSK_WPA2;
+        } else if (wpa) {
+            return PSK_WPA;
+        } else {
+            Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
+            return PSK_UNKNOWN;
+        }
+    }
+
+    private static int getSecurity(ScanResult result) {
+        if (result.capabilities.contains("WEP")) {
+            return SECURITY_WEP;
+        } else if (result.capabilities.contains("PSK")) {
+            return SECURITY_PSK;
+        } else if (result.capabilities.contains("EAP")) {
+            return SECURITY_EAP;
+        }
+        return SECURITY_NONE;
+    }
+
+    static int getSecurity(WifiConfiguration config) {
+        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+            return SECURITY_PSK;
+        }
+        if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
+                config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+            return SECURITY_EAP;
+        }
+        return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
+    }
+
+    public static String securityToString(int security, int pskType) {
+        if (security == SECURITY_WEP) {
+            return "WEP";
+        } else if (security == SECURITY_PSK) {
+            if (pskType == PSK_WPA) {
+                return "WPA";
+            } else if (pskType == PSK_WPA2) {
+                return "WPA2";
+            } else if (pskType == PSK_WPA_WPA2) {
+                return "WPA_WPA2";
+            }
+            return "PSK";
+        } else if (security == SECURITY_EAP) {
+            return "EAP";
+        }
+        return "NONE";
+    }
+
+    static String removeDoubleQuotes(String string) {
+        int length = string.length();
+        if ((length > 1) && (string.charAt(0) == '"')
+                && (string.charAt(length - 1) == '"')) {
+            return string.substring(1, length - 1);
+        }
+        return string;
+    }
+
+    public interface AccessPointListener {
+        void onAccessPointChanged(AccessPoint accessPoint);
+        void onLevelChanged(AccessPoint accessPoint);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
new file mode 100644
index 0000000..c3e23d2
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.wifi;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Message;
+import android.widget.Toast;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.R;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Tracks saved or available wifi networks and their state.
+ */
+public class WifiTracker {
+    private static final String TAG = "WifiTracker";
+
+    /** verbose logging flag. this flag is set thru developer debugging options
+     * and used so as to assist with in-the-field WiFi connectivity debugging  */
+    public static int sVerboseLogging = 0;
+
+    // TODO: Allow control of this?
+    // Combo scans can take 5-6s to complete - set to 10s.
+    private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;
+
+    private final Context mContext;
+    private final WifiManager mWifiManager;
+    private final IntentFilter mFilter;
+
+    private final AtomicBoolean mConnected = new AtomicBoolean(false);
+    private final WifiListener mListener;
+    private final boolean mIncludeSaved;
+    private final boolean mIncludeScans;
+
+    private boolean mSavedNetworksExist;
+    private boolean mRegistered;
+    private ArrayList<AccessPoint> mAccessPoints = new ArrayList<>();
+    private ArrayList<AccessPoint> mCachedAccessPoints = new ArrayList<>();
+
+    private NetworkInfo mLastNetworkInfo;
+    private WifiInfo mLastInfo;
+
+    @VisibleForTesting
+    Scanner mScanner;
+
+    public WifiTracker(Context context, WifiListener wifiListener, boolean includeSaved,
+            boolean includeScans) {
+        this(context, wifiListener, includeSaved, includeScans,
+                (WifiManager) context.getSystemService(Context.WIFI_SERVICE));
+    }
+
+    @VisibleForTesting
+    WifiTracker(Context context, WifiListener wifiListener, boolean includeSaved,
+            boolean includeScans, WifiManager wifiManager) {
+        if (!includeSaved && !includeScans) {
+            throw new IllegalArgumentException("Must include either saved or scans");
+        }
+        mContext = context;
+        mWifiManager = wifiManager;
+        mIncludeSaved = includeSaved;
+        mIncludeScans = includeScans;
+        mListener = wifiListener;
+
+        // check if verbose logging has been turned on or off
+        sVerboseLogging = mWifiManager.getVerboseLoggingLevel();
+
+        mFilter = new IntentFilter();
+        mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+        mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+    }
+
+    /**
+     * Forces an update of the wifi networks when not scanning.
+     */
+    public void forceUpdate() {
+        updateAccessPoints();
+    }
+
+    /**
+     * Force a scan for wifi networks to happen now.
+     */
+    public void forceScan() {
+        if (mWifiManager.isWifiEnabled() && mScanner != null) {
+            mScanner.forceScan();
+        }
+    }
+
+    /**
+     * Temporarily stop scanning for wifi networks.
+     */
+    public void pauseScanning() {
+        if (mScanner != null) {
+            mScanner.pause();
+        }
+    }
+
+    /**
+     * Resume scanning for wifi networks after it has been paused.
+     */
+    public void resumeScanning() {
+        if (mWifiManager.isWifiEnabled()) {
+            if (mScanner == null) {
+                mScanner = new Scanner();
+            }
+            mScanner.resume();
+        }
+        updateAccessPoints();
+    }
+
+    /**
+     * Start tracking wifi networks.
+     * Registers listeners and starts scanning for wifi networks. If this is not called
+     * then forceUpdate() must be called to populate getAccessPoints().
+     */
+    public void startTracking() {
+        resumeScanning();
+        if (!mRegistered) {
+            mContext.registerReceiver(mReceiver, mFilter);
+            mRegistered = true;
+        }
+    }
+
+    /**
+     * Stop tracking wifi networks.
+     * Unregisters all listeners and stops scanning for wifi networks. This should always
+     * be called when done with a WifiTracker (if startTracking was called) to ensure
+     * proper cleanup.
+     */
+    public void stopTracking() {
+        if (mRegistered) {
+            mContext.unregisterReceiver(mReceiver);
+            mRegistered = false;
+        }
+        pauseScanning();
+    }
+
+    /**
+     * Gets the current list of access points.
+     */
+    public List<AccessPoint> getAccessPoints() {
+        return mAccessPoints;
+    }
+
+    public WifiManager getManager() {
+        return mWifiManager;
+    }
+
+    public boolean isWifiEnabled() {
+        return mWifiManager.isWifiEnabled();
+    }
+
+    /**
+     * @return true when there are saved networks on the device, regardless
+     * of whether the WifiTracker is tracking saved networks.
+     */
+    public boolean doSavedNetworksExist() {
+        return mSavedNetworksExist;
+    }
+
+    public boolean isConnected() {
+        return mConnected.get();
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("  - wifi tracker ------");
+        for (AccessPoint accessPoint : mAccessPoints) {
+            pw.println("  " + accessPoint);
+        }
+    }
+
+    private void updateAccessPoints() {
+        // Swap the current access points into a cached list.
+        ArrayList<AccessPoint> tmpSwp = mAccessPoints;
+        mAccessPoints = mCachedAccessPoints;
+        mCachedAccessPoints = tmpSwp;
+        // Clear out the configs so we don't think something is saved when it isn't.
+        for (AccessPoint accessPoint : mCachedAccessPoints) {
+            accessPoint.clearConfig();
+        }
+
+        mAccessPoints.clear();
+
+        /** Lookup table to more quickly update AccessPoints by only considering objects with the
+         * correct SSID.  Maps SSID -> List of AccessPoints with the given SSID.  */
+        Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
+
+        final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+        if (configs != null) {
+            mSavedNetworksExist = configs.size() != 0;
+            for (WifiConfiguration config : configs) {
+                if (config.selfAdded && config.numAssociation == 0) {
+                    continue;
+                }
+                AccessPoint accessPoint = getCachedOrCreate(config);
+                if (mLastInfo != null && mLastNetworkInfo != null) {
+                    accessPoint.update(mLastInfo, mLastNetworkInfo);
+                }
+                if (mIncludeSaved) {
+                    mAccessPoints.add(accessPoint);
+                    apMap.put(accessPoint.getSsid(), accessPoint);
+                } else {
+                    // If we aren't using saved networks, drop them into the cache so that
+                    // we have access to their saved info.
+                    mCachedAccessPoints.add(accessPoint);
+                }
+            }
+        }
+
+        final List<ScanResult> results = mWifiManager.getScanResults();
+        if (results != null) {
+            for (ScanResult result : results) {
+                // Ignore hidden and ad-hoc networks.
+                if (result.SSID == null || result.SSID.length() == 0 ||
+                        result.capabilities.contains("[IBSS]")) {
+                    continue;
+                }
+
+                boolean found = false;
+                for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
+                    if (accessPoint.update(result)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found && mIncludeScans) {
+                    AccessPoint accessPoint = getCachedOrCreate(result);
+                    if (mLastInfo != null && mLastNetworkInfo != null) {
+                        accessPoint.update(mLastInfo, mLastNetworkInfo);
+                    }
+                    mAccessPoints.add(accessPoint);
+                    apMap.put(accessPoint.getSsid(), accessPoint);
+                }
+            }
+        }
+
+        // Pre-sort accessPoints to speed preference insertion
+        Collections.sort(mAccessPoints);
+        if (mListener != null) {
+            mListener.onAccessPointsChanged();
+        }
+    }
+
+    private AccessPoint getCachedOrCreate(ScanResult result) {
+        final int N = mCachedAccessPoints.size();
+        for (int i = 0; i < N; i++) {
+            if (mCachedAccessPoints.get(i).matches(result)) {
+                AccessPoint ret = mCachedAccessPoints.remove(i);
+                ret.update(result);
+                return ret;
+            }
+        }
+        return new AccessPoint(mContext, result);
+    }
+
+    private AccessPoint getCachedOrCreate(WifiConfiguration config) {
+        final int N = mCachedAccessPoints.size();
+        for (int i = 0; i < N; i++) {
+            if (mCachedAccessPoints.get(i).matches(config)) {
+                AccessPoint ret = mCachedAccessPoints.remove(i);
+                ret.loadConfig(config);
+                return ret;
+            }
+        }
+        return new AccessPoint(mContext, config);
+    }
+
+    private void updateNetworkInfo(NetworkInfo networkInfo) {
+        /* sticky broadcasts can call this when wifi is disabled */
+        if (!mWifiManager.isWifiEnabled()) {
+            mScanner.pause();
+            return;
+        }
+
+        if (networkInfo != null &&
+                networkInfo.getDetailedState() == DetailedState.OBTAINING_IPADDR) {
+            mScanner.pause();
+        } else {
+            mScanner.resume();
+        }
+
+        mLastInfo = mWifiManager.getConnectionInfo();
+        if (networkInfo != null) {
+            mLastNetworkInfo = networkInfo;
+        }
+
+        boolean reorder = false;
+        for (int i = mAccessPoints.size() - 1; i >= 0; --i) {
+            if (mAccessPoints.get(i).update(mLastInfo, mLastNetworkInfo)) {
+                reorder = true;
+            }
+        }
+        if (reorder) {
+            Collections.sort(mAccessPoints);
+            if (mListener != null) {
+                mListener.onAccessPointsChanged();
+            }
+        }
+    }
+
+    private void updateWifiState(int state) {
+        if (state == WifiManager.WIFI_STATE_ENABLED) {
+            mScanner.resume();
+        } else {
+            mLastInfo = null;
+            mLastNetworkInfo = null;
+            mScanner.pause();
+        }
+        if (mListener != null) {
+            mListener.onWifiStateChanged(state);
+        }
+    }
+
+    public static List<AccessPoint> getCurrentAccessPoints(Context context, boolean includeSaved,
+            boolean includeScans) {
+        WifiTracker tracker = new WifiTracker(context, null, includeSaved, includeScans);
+        tracker.forceUpdate();
+        return tracker.getAccessPoints();
+    }
+
+    @VisibleForTesting
+    final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN));
+            } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) ||
+                    WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) ||
+                    WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
+                updateAccessPoints();
+            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
+                NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(
+                        WifiManager.EXTRA_NETWORK_INFO);
+                mConnected.set(info.isConnected());
+                if (mListener != null) {
+                    mListener.onConnectedChanged();
+                }
+                updateAccessPoints();
+                updateNetworkInfo(info);
+            } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
+                updateNetworkInfo(null);
+            }
+        }
+    };
+
+    @VisibleForTesting
+    class Scanner extends Handler {
+        private int mRetry = 0;
+
+        void resume() {
+            if (!hasMessages(0)) {
+                sendEmptyMessage(0);
+            }
+        }
+
+        void forceScan() {
+            removeMessages(0);
+            sendEmptyMessage(0);
+        }
+
+        void pause() {
+            mRetry = 0;
+            removeMessages(0);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            if (mWifiManager.startScan()) {
+                mRetry = 0;
+            } else if (++mRetry >= 3) {
+                mRetry = 0;
+                if (mContext != null) {
+                    Toast.makeText(mContext, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
+                }
+                return;
+            }
+            sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
+        }
+    }
+
+    /** A restricted multimap for use in constructAccessPoints */
+    private static class Multimap<K,V> {
+        private final HashMap<K,List<V>> store = new HashMap<K,List<V>>();
+        /** retrieve a non-null list of values with key K */
+        List<V> getAll(K key) {
+            List<V> values = store.get(key);
+            return values != null ? values : Collections.<V>emptyList();
+        }
+
+        void put(K key, V val) {
+            List<V> curVals = store.get(key);
+            if (curVals == null) {
+                curVals = new ArrayList<V>(3);
+                store.put(key, curVals);
+            }
+            curVals.add(val);
+        }
+    }
+
+    public interface WifiListener {
+        /**
+         * Called when the state of Wifi has changed, the state will be one of
+         * the following.
+         *
+         * <li>{@link WifiManager#WIFI_STATE_DISABLED}</li>
+         * <li>{@link WifiManager#WIFI_STATE_ENABLED}</li>
+         * <li>{@link WifiManager#WIFI_STATE_DISABLING}</li>
+         * <li>{@link WifiManager#WIFI_STATE_ENABLING}</li>
+         * <li>{@link WifiManager#WIFI_STATE_UNKNOWN}</li>
+         * <p>
+         *
+         * @param state The new state of wifi.
+         */
+        void onWifiStateChanged(int state);
+
+        /**
+         * Called when the connection state of wifi has changed and isConnected
+         * should be called to get the updated state.
+         */
+        void onConnectedChanged();
+
+        /**
+         * Called to indicate the list of AccessPoints has been updated and
+         * getAccessPoints should be called to get the latest information.
+         */
+        void onAccessPointsChanged();
+    }
+}
diff --git a/packages/SettingsLib/tests/Android.mk b/packages/SettingsLib/tests/Android.mk
new file mode 100644
index 0000000..d3ffffa
--- /dev/null
+++ b/packages/SettingsLib/tests/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+
+LOCAL_PACKAGE_NAME := SettingsLibTests
+
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+
+include frameworks/base/packages/SettingsLib/common.mk
+
+include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/tests/AndroidManifest.xml b/packages/SettingsLib/tests/AndroidManifest.xml
new file mode 100644
index 0000000..00d16fc
--- /dev/null
+++ b/packages/SettingsLib/tests/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settingslib">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.settingslib"
+        android:label="Tests for SettingsLib">
+    </instrumentation>
+</manifest>
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/BaseTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/BaseTest.java
new file mode 100644
index 0000000..04a568e
--- /dev/null
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/BaseTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.test.AndroidTestCase;
+
+public class BaseTest extends AndroidTestCase {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Mockito stuff.
+        System.setProperty("dexmaker.dexcache", mContext.getCacheDir().getPath());
+        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+    }
+
+}
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
new file mode 100644
index 0000000..4ac461d
--- /dev/null
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.wifi;
+
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+
+import com.android.settingslib.BaseTest;
+import com.android.settingslib.wifi.AccessPoint.AccessPointListener;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+// TODO: Add some coverage
+public class AccessPointTest extends BaseTest {
+
+    private static final String TEST_SSID = "TestSsid";
+    private static final int NETWORK_ID = 0;
+
+    private AccessPointListener mAccessPointListener;
+    private AccessPoint mAccessPoint;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mAccessPointListener = Mockito.mock(AccessPointListener.class);
+
+        WifiConfiguration wifiConfig = new WifiConfiguration();
+        wifiConfig.networkId = NETWORK_ID;
+        wifiConfig.SSID = TEST_SSID;
+
+        mAccessPoint = new AccessPoint(mContext, wifiConfig);
+        mAccessPoint.setListener(mAccessPointListener);
+    }
+
+    public void testOnLevelChanged() {
+        ScanResult result = new ScanResult();
+        result.capabilities = "";
+        result.SSID = TEST_SSID;
+
+        // Give it a level.
+        result.level = WifiTrackerTest.levelToRssi(1);
+        mAccessPoint.update(result);
+        verifyOnLevelChangedCallback(1);
+
+        // Give it a better level.
+        result.level = WifiTrackerTest.levelToRssi(2);
+        mAccessPoint.update(result);
+        verifyOnLevelChangedCallback(1);
+    }
+
+    public void testOnAccessPointChangedCallback() {
+        WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
+        Mockito.when(wifiInfo.getNetworkId()).thenReturn(NETWORK_ID);
+
+        mAccessPoint.update(wifiInfo, null);
+        verifyOnAccessPointsCallback(1);
+
+        mAccessPoint.update(null, null);
+        verifyOnAccessPointsCallback(2);
+
+        ScanResult result = new ScanResult();
+        result.capabilities = "";
+        result.SSID = TEST_SSID;
+        mAccessPoint.update(result);
+        verifyOnAccessPointsCallback(3);
+    }
+
+    private void verifyOnLevelChangedCallback(int num) {
+        ArgumentCaptor<AccessPoint> accessPoint = ArgumentCaptor.forClass(AccessPoint.class);
+        Mockito.verify(mAccessPointListener, Mockito.atLeast(num))
+                .onLevelChanged(accessPoint.capture());
+        assertEquals(mAccessPoint, accessPoint.getValue());
+    }
+
+    private void verifyOnAccessPointsCallback(int num) {
+        ArgumentCaptor<AccessPoint> accessPoint = ArgumentCaptor.forClass(AccessPoint.class);
+        Mockito.verify(mAccessPointListener, Mockito.atLeast(num))
+                .onAccessPointChanged(accessPoint.capture());
+        assertEquals(mAccessPoint, accessPoint.getValue());
+    }
+
+}
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java
new file mode 100644
index 0000000..73d4938
--- /dev/null
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.wifi;
+
+import android.content.Intent;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
+import android.util.Log;
+
+import com.android.settingslib.BaseTest;
+import com.android.settingslib.wifi.WifiTracker.WifiListener;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class WifiTrackerTest extends BaseTest {
+
+    private static final String TAG = "WifiTrackerTest";
+
+    private static final String[] TEST_SSIDS = new String[] {
+        "TEST_SSID_1",
+        "TEST_SSID_2",
+        "TEST_SSID_3",
+        "TEST_SSID_4",
+        "TEST_SSID_5",
+    };
+    private static final int NUM_NETWORKS = 5;
+
+    private WifiManager mWifiManager;
+    private WifiListener mWifiListener;
+
+    private WifiTracker mWifiTracker;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mWifiManager = Mockito.mock(WifiManager.class);
+        mWifiListener = Mockito.mock(WifiListener.class);
+        mWifiTracker = new WifiTracker(mContext, mWifiListener, true, true, mWifiManager);
+        mWifiTracker.mScanner = mWifiTracker.new Scanner();
+        Mockito.when(mWifiManager.isWifiEnabled()).thenReturn(true);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        mWifiTracker.dump(pw);
+        pw.flush();
+        Log.d(TAG, sw.toString());
+        super.tearDown();
+    }
+
+    public void testAccessPointsCallback() {
+        sendScanResultsAvailable();
+
+        Mockito.verify(mWifiListener, Mockito.atLeastOnce()).onAccessPointsChanged();
+    }
+
+    public void testConnectedCallback() {
+        sendConnected();
+
+        Mockito.verify(mWifiListener, Mockito.atLeastOnce()).onConnectedChanged();
+        assertEquals(true, mWifiTracker.isConnected());
+    }
+
+    public void testWifiStateCallback() {
+        final int TEST_WIFI_STATE = WifiManager.WIFI_STATE_ENABLED;
+
+        Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        i.putExtra(WifiManager.EXTRA_WIFI_STATE, TEST_WIFI_STATE);
+        mWifiTracker.mReceiver.onReceive(mContext, i);
+
+        ArgumentCaptor<Integer> wifiState = ArgumentCaptor.forClass(Integer.class);
+        Mockito.verify(mWifiListener, Mockito.atLeastOnce())
+                .onWifiStateChanged(wifiState.capture());
+        assertEquals(TEST_WIFI_STATE, (int) wifiState.getValue());
+    }
+
+    public void testScanner() {
+        // TODO: Figure out how to verify more of the Scanner functionality.
+        // Make scans be successful.
+        Mockito.when(mWifiManager.startScan()).thenReturn(true);
+
+        mWifiTracker.mScanner.handleMessage(null);
+        Mockito.verify(mWifiManager, Mockito.atLeastOnce()).startScan();
+    }
+
+    public void testNetworkSorting() {
+        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
+        List<ScanResult> scanResults = new ArrayList<ScanResult>();
+        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, true);
+
+        // Tell WifiTracker we are connected now.
+        sendConnected();
+
+        // Send all of the configs and scan results to the tracker.
+        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
+        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
+        sendScanResultsAvailable();
+
+        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
+        assertEquals("Expected number of results", NUM_NETWORKS, accessPoints.size());
+        for (int i = 0; i < NUM_NETWORKS; i++) {
+            assertEquals("Verifying slot " + i, expectedSsids[i], accessPoints.get(i).getSsid());
+        }
+    }
+
+    public void testSavedOnly() {
+        mWifiTracker = new WifiTracker(mContext, mWifiListener, true, false, mWifiManager);
+        mWifiTracker.mScanner = mWifiTracker.new Scanner();
+
+        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
+        List<ScanResult> scanResults = new ArrayList<ScanResult>();
+        generateTestNetworks(wifiConfigs, scanResults, true);
+
+        // Tell WifiTracker we are connected now.
+        sendConnected();
+
+        // Send all of the configs and scan results to the tracker.
+        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
+        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
+        sendScanResultsAvailable();
+
+        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
+        // Only expect the first two to come back in the results.
+        assertEquals("Expected number of results", 2, accessPoints.size());
+        assertEquals(TEST_SSIDS[1], accessPoints.get(0).getSsid());
+        assertEquals(TEST_SSIDS[0], accessPoints.get(1).getSsid());
+    }
+
+    public void testAvailableOnly() {
+        mWifiTracker = new WifiTracker(mContext, mWifiListener, false, true, mWifiManager);
+        mWifiTracker.mScanner = mWifiTracker.new Scanner();
+
+        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
+        List<ScanResult> scanResults = new ArrayList<ScanResult>();
+        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, true);
+
+        // Tell WifiTracker we are connected now.
+        sendConnected();
+
+        // Send all of the configs and scan results to the tracker.
+        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
+        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
+        sendScanResultsAvailable();
+
+        // Expect the last one (sorted order) to be left off since its only saved.
+        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
+        assertEquals("Expected number of results", NUM_NETWORKS - 1, accessPoints.size());
+        for (int i = 0; i < NUM_NETWORKS - 1; i++) {
+            assertEquals("Verifying slot " + i, expectedSsids[i], accessPoints.get(i).getSsid());
+        }
+    }
+
+    public void testNonEphemeralConnected() {
+        mWifiTracker = new WifiTracker(mContext, mWifiListener, false, true, mWifiManager);
+        mWifiTracker.mScanner = mWifiTracker.new Scanner();
+
+        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
+        List<ScanResult> scanResults = new ArrayList<ScanResult>();
+        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, false);
+
+        // Tell WifiTracker we are connected now.
+        sendConnected();
+
+        // Send all of the configs and scan results to the tracker.
+        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
+        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
+        sendScanResultsAvailable();
+        // Do this twice to catch a bug that was happening in the caching, making things ephemeral.
+        sendScanResultsAvailable();
+
+        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
+        assertEquals("Expected number of results", NUM_NETWORKS - 1, accessPoints.size());
+        assertFalse("Connection is not ephemeral", accessPoints.get(0).isEphemeral());
+        assertTrue("Connected to wifi", accessPoints.get(0).isActive());
+    }
+
+    private String[] generateTestNetworks(List<WifiConfiguration> wifiConfigs,
+            List<ScanResult> scanResults, boolean connectedIsEphemeral) {
+        String[] expectedSsids = new String[NUM_NETWORKS];
+
+        // First is just saved;
+        addConfig(wifiConfigs, TEST_SSIDS[0]);
+        // This should come last since its not available.
+        expectedSsids[4] = TEST_SSIDS[0];
+
+        // Second is saved and available.
+        addConfig(wifiConfigs, TEST_SSIDS[1]);
+        addResult(scanResults, TEST_SSIDS[1], 0);
+        // This one is going to have a couple extra results, to verify de-duplication.
+        addResult(scanResults, TEST_SSIDS[1], 2);
+        addResult(scanResults, TEST_SSIDS[1], 1);
+        // This should come second since it is available and saved but not connected.
+        expectedSsids[1] = TEST_SSIDS[1];
+
+        // Third is just available, but higher rssi.
+        addResult(scanResults, TEST_SSIDS[2], 3);
+        // This comes after the next one since it has a lower rssi.
+        expectedSsids[3] = TEST_SSIDS[2];
+
+        // Fourth also just available but with even higher rssi.
+        addResult(scanResults, TEST_SSIDS[3], 4);
+        // This is the highest rssi but not saved so it should be after the saved+availables.
+        expectedSsids[2] = TEST_SSIDS[3];
+
+        // Last is going to be connected.
+        int netId = WifiConfiguration.INVALID_NETWORK_ID;
+        if (!connectedIsEphemeral) {
+            netId = addConfig(wifiConfigs, TEST_SSIDS[4]);
+        }
+        addResult(scanResults, TEST_SSIDS[4], 2);
+        // Setup wifi connection to be this one.
+        WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
+        Mockito.when(wifiInfo.getSSID()).thenReturn(TEST_SSIDS[4]);
+        Mockito.when(wifiInfo.getNetworkId()).thenReturn(netId);
+        Mockito.when(mWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
+        // This should come first since it is connected.
+        expectedSsids[0] = TEST_SSIDS[4];
+
+        return expectedSsids;
+    }
+
+    private void addResult(List<ScanResult> results, String ssid, int level) {
+        results.add(new ScanResult(WifiSsid.createFromAsciiEncoded(ssid),
+                ssid, ssid, levelToRssi(level), AccessPoint.LOWER_FREQ_24GHZ, 0));
+    }
+
+    public static int levelToRssi(int level) {
+        // Reverse level to rssi calculation based off from WifiManager.calculateSignalLevel.
+        final int MAX_RSSI = -55;
+        final int MIN_RSSI = -100;
+        final int NUM_LEVELS = 4;
+        return level * (MAX_RSSI - MIN_RSSI) / (NUM_LEVELS - 1) + MIN_RSSI;
+    }
+
+    private int addConfig(List<WifiConfiguration> configs, String ssid) {
+        WifiConfiguration config = new WifiConfiguration();
+        config.networkId = configs.size();
+        config.SSID = '"' + ssid + '"';
+        configs.add(config);
+        return config.networkId;
+    }
+
+    private void sendConnected() {
+        NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class);
+        Mockito.when(networkInfo.isConnected()).thenReturn(true);
+        Mockito.when(networkInfo.getState()).thenReturn(State.CONNECTED);
+        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
+        mWifiTracker.mReceiver.onReceive(mContext, intent);
+    }
+
+    private void sendScanResultsAvailable() {
+        Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+        mWifiTracker.mReceiver.onReceive(mContext, i);
+    }
+
+}
diff --git a/packages/SettingsProvider/res/values-tl/strings.xml b/packages/SettingsProvider/res/values-tl/strings.xml
index 19219ec..0fe535e 100644
--- a/packages/SettingsProvider/res/values-tl/strings.xml
+++ b/packages/SettingsProvider/res/values-tl/strings.xml
@@ -19,5 +19,5 @@
 
 <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="4567566098528588863">"Imbakan ng Mga Setting"</string>
+    <string name="app_label" msgid="4567566098528588863">"Storage ng Mga Setting"</string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 175b424..6a05af1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2236,10 +2236,7 @@
                     ringerModeAffectedStreams);
 
             loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
-                    ((1 << AudioManager.STREAM_MUSIC) |
-                     (1 << AudioManager.STREAM_RING) |
-                     (1 << AudioManager.STREAM_NOTIFICATION) |
-                     (1 << AudioManager.STREAM_SYSTEM)));
+                    AudioService.DEFAULT_MUTE_STREAMS_AFFECTED);
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index 2e95b4e..ed0697e 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -21,5 +21,5 @@
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Hata raporunuzu paylaşmak için hızlıca sola kaydırın"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Hata raporunuzu paylaşmak için dokunun"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Hata raporları, kişisel ve özel bilgiler dahil olmak üzere sistemin çeşitli günlük dosyalarından veriler içerir. Hata raporlarını sadece güvendiğiniz uygulamalar ve kişilerle paylaşın."</string>
-    <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bir dahaki sefere bu mesajı göster"</string>
+    <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bir dahaki sefere bu iletiyi göster"</string>
 </resources>
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 2ff9a28..47ef42a 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -20,6 +20,8 @@
     $(LOCAL_PATH)/res
 LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.keyguard
 
+include frameworks/base/packages/SettingsLib/common.mk
+
 include $(BUILD_PACKAGE)
 
 ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 4cf4f52d..01b2713 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -21,7 +21,8 @@
     android:id="@+id/keyguard_bottom_area"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
-    >
+    android:outlineProvider="none"
+    android:elevation="5dp" > <!-- Put it above the status bar header -->
 
     <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
         android:id="@+id/keyguard_indication_text"
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index ea2e1e1..0ba3ba3 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -39,6 +39,7 @@
             android:id="@android:id/title"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:ellipsize="end"
             android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
 
         <TextView
@@ -58,4 +59,4 @@
         android:scaleType="center"
         android:src="@drawable/ic_qs_cancel" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 8f367a6..26523f9 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -15,7 +15,7 @@
 -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent" 
+    android:layout_width="match_parent"
     android:layout_height="match_parent">
     <!-- Status Bar Scrim View -->
     <ImageView
@@ -29,9 +29,16 @@
     <!-- Recents View -->
     <com.android.systemui.recents.views.RecentsView
         android:id="@+id/recents_view"
-        android:layout_width="match_parent" 
+        android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:focusable="true" />
+        android:focusable="true">
+        <!-- MultiStack Debug View -->
+        <ViewStub android:id="@+id/multistack_debug_view_stub"
+               android:layout="@layout/recents_multistack_debug"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_gravity="left|bottom" />
+    </com.android.systemui.recents.views.RecentsView>
 
     <!-- Empty View -->
     <ViewStub android:id="@+id/empty_view_stub"
diff --git a/packages/SystemUI/res/layout/recents_multistack_debug.xml b/packages/SystemUI/res/layout/recents_multistack_debug.xml
new file mode 100644
index 0000000..6524a54
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_multistack_debug.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="left|bottom"
+    android:orientation="vertical">
+    <Button
+        android:id="@+id/add_stack"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:padding="8dp"
+        android:textSize="20sp"
+        android:textColor="#ffffffff"
+        android:text="@string/recents_multistack_add_stack"
+        android:fontFamily="sans-serif"
+        android:background="#000000"
+        android:alpha="0.5" />
+    <Button
+        android:id="@+id/resize_stack"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:padding="8dp"
+        android:textSize="20sp"
+        android:textColor="#ffffffff"
+        android:text="@string/recents_multistack_resize_stack"
+        android:fontFamily="sans-serif"
+        android:background="#000000"
+        android:alpha="0.5" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_multistack_stack_size_dialog.xml b/packages/SystemUI/res/layout/recents_multistack_stack_size_dialog.xml
new file mode 100644
index 0000000..36e54a0
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_multistack_stack_size_dialog.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:padding="16dp"
+    android:orientation="vertical"
+    android:descendantFocusability="beforeDescendants"
+    android:focusableInTouchMode="true">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <EditText
+            android:id="@+id/inset_left"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:hint="Left"
+            android:singleLine="true"
+            android:imeOptions="actionNext"
+            android:inputType="number"
+            android:selectAllOnFocus="true" />
+        <EditText
+            android:id="@+id/inset_top"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:hint="Top"
+            android:singleLine="true"
+            android:imeOptions="actionNext"
+            android:inputType="number"
+            android:selectAllOnFocus="true" />
+        <EditText
+            android:id="@+id/inset_right"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:hint="Right"
+            android:singleLine="true"
+            android:imeOptions="actionNext"
+            android:inputType="number"
+            android:selectAllOnFocus="true" />
+        <EditText
+            android:id="@+id/inset_bottom"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:hint="Bottom"
+            android:singleLine="true"
+            android:imeOptions="actionDone"
+            android:inputType="number"
+            android:selectAllOnFocus="true" />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index f1d8ad0..53047a3 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -43,6 +43,16 @@
         android:ellipsize="marquee"
         android:fadingEdge="horizontal" />
     <com.android.systemui.recents.views.FixedSizeImageView
+        android:id="@+id/move_task"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_marginEnd="52dp"
+        android:layout_gravity="center_vertical|end"
+        android:padding="12dp"
+        android:background="@drawable/recents_button_bg"
+        android:src="@drawable/star"
+        android:visibility="gone" />
+    <com.android.systemui.recents.views.FixedSizeImageView
         android:id="@+id/dismiss_task"
         android:layout_width="48dp"
         android:layout_height="48dp"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 428c9f4..ba2c8eb 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kon nie <xliff:g id="APP">%s</xliff:g> begin nie."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Maak alle programme toe"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Gelaai"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laai tans"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tot vol"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e57c5f4..f4ba6f6 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ሁሉንም ማመልከቻዎች አሰናብት"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ኃይል በመሙላት ላይ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> እስኪሞላ ድረስ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 44f4948..67e151e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"تعذر بدء <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"تجاهل كل التطبيقات"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"تم الشحن"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"جارٍ الشحن"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> حتى الاكتمال"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 7fc379c..4d37f4a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -191,10 +191,10 @@
     <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Затваряне на панела."</string>
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Повече време."</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"По-малко време."</string>
-    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Светкавицата е изключена."</string>
-    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Светкавицата е включена."</string>
-    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Светкавицата се изключи."</string>
-    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Светкавицата се включи."</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фенерчето е изключено."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фенерчето е включено."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фенерчето е изключено."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фенерчето е включено."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"Функцията за инвертиране на цветовете се изключи."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="6897462320184911126">"Функцията за инвертиране на цветовете се включи."</string>
     <string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Мобилната точка за достъп се изключи."</string>
@@ -268,7 +268,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="quick_settings_flashlight_label" msgid="2133093497691661546">"Светкавица"</string>
+    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фенерче"</string>
     <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Мобилни данни"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Пренос на данни"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Оставащи данни"</string>
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Отхвърляне на всички приложения"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарежда се"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до пълно зареждане"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 1110310..71c78b2 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"সমস্ত অ্যাপ্লিকেশন খারিজ করুন"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"চার্জ হয়েছে"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"চার্জ হচ্ছে"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"পূর্ণ হতে <xliff:g id="CHARGING_TIME">%s</xliff:g> সময় লাগবে"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ef5986b..16d5d109 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Descarta totes les aplicacions"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"S\'està carregant"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> per completar la càrrega"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 6235eb1..c949164 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odstranit všechny aplikace"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíjení"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do plného nabití"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 3153d3f..733f0c9 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Luk alle applikationer"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Oplader"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> indtil fuld opladet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3165a3c..9d0b907 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Alle Apps entfernen"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Wird aufgeladen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Voll in <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index e6ea177..5e672b3 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Παράβλεψη όλων των εφαρμογών"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Φόρτιση"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> για πλήρη φόρτιση"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 8e46cce..0d627cf 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Dismiss all applications"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charging"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> until full"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 8e46cce..0d627cf 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Dismiss all applications"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charging"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> until full"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index c788677..a70ef9a 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Descartar todas las aplicaciones"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 3f2fa15..54926ce 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ignorar todas las aplicaciones"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 9c05158..cb2dd7b 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Loobu kõikidest rakendustest"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laadimine"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Täislaadimiseks kulub <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index e2a81e9..ae02787 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -159,7 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
-    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazioen atala garbitu da."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazio guztiak baztertu da."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> hasten."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Jakinarazpena baztertu da."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Jakinarazpenen panela."</string>
@@ -281,7 +281,19 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Garbitu aplikazio guztiak"</string>
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Baztertu aplikazio guztiak"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Kargatzen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> falta zaizkio guztiz kargatzeko"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index c50eabf..becc464 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> شروع نشد."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"رد کردن همه برنامه‌ها"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"شارژ کامل شد"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"در حال شارژ شدن"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> مانده تا شارژ کامل شود"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3208b1b..5fbe650 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Hylkää kaikki sovellukset"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Ladataan"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> kunnes täynnä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index e6bd1f6..daf87ef 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Supprimer toutes les applications"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charge en cours..."</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargée dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1d91c8a..32dac57 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Supprimer toutes les applications"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"En charge"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargé dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 78a5fbb..8b1a3da 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Rexeitar todas as aplicacións"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completar a carga"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 411e3c3..34040d1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सभी ऐप्लिकेशन ख़ारिज करें"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हो रही है"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"पूर्ण होने में <xliff:g id="CHARGING_TIME">%s</xliff:g> शेष"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1e42832..5fc2f88 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odbaci sve aplikacije"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napunjenosti"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index ed105d0..8b0edbc 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Összes alkalmazás elvetése"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Töltés"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> a teljes töltöttségig"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 6432060..2fa89c8 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Հեռացնել բոլոր հավելվածները"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Լիցքավորվում է"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Լրիվ լիցքավորմանը մնաց <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index bd0a99f..501b99e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -159,7 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
-    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru ditutup."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru telah ditutup."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulai <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan disingkirkan."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bayangan pemberitahuan."</string>
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Tutup semua aplikasi"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengisi daya"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> sampai penuh"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index adcda3f..a408204 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Fjarlægja öll forrit"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Fullhlaðin"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Í hleðslu"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> þar til fullri hleðslu er náð"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 21a483f..369e51a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Rimuovi tutte le applicazioni"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"In carica"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> al termine della carica"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 15bd235..bdfdcc3 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"לא ניתן היה להפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"סגור את כל האפליקציות"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"טעון"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"טוען"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> עד למילוי"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 5b68f86..330e55a 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"すべてのアプリケーションを消去"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電しています"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"充電完了まで<xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index b6650d0..26b4025 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ყველა აპლიკაციის გაუქმება"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"მიმდინარეობს დატენვა"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> სრულად დატენვამდე"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 15c4584..6258a8c 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Барлық қолданбаларды қабылдамау"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зарядталды"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядталуда"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Толғанға дейін <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 28d586a..71d616f 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"មិន​អាច​ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"បោះបង់កម្មវិធីទាំងអស់"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បាន​បញ្ចូល​ថ្ម​​"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"កំពុង​បញ្ចូល​ថ្ម"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> រហូត​ដល់ពេញ"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 4134c11..b2e2a1a 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ಪೂರ್ಣಗೊಳ್ಳುವವರೆಗೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 549da84..a0d614a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"모든 애플리케이션 닫기"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"충전 중"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"완충까지 <xliff:g id="CHARGING_TIME">%s</xliff:g> 남음"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 960541a..f51814f 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -307,6 +307,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Бардык колдонмолорду көз жаздымда калтыруу"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Кубатталды"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Кубатталууда"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> толгонго чейин"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 33e98b2..01ef31a 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"ບໍ່​ສາ​ມາດ​ເລີ່ມ <xliff:g id="APP">%s</xliff:g> ໄດ້."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ປ່ອຍ​ທຸກ​ແອັບ​ພ​ລິ​ເຄ"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ສາກເຕັມແລ້ວ."</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ກຳລັງສາກໄຟ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ຈຶ່ງ​ຈະ​ເຕັມ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index f7a8c00..50fdaff 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Atsisakyti visų programų"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Kraunamas"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> iki visiško įkrovimo"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a9f7110..4d36ab5 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Noņemt visas lietojumprogrammas"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Notiek uzlāde"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> līdz pilnam akumulatoram"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 4686ba5..a026e6f 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Отфрли ги сите апликации"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Наполнета"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Се полни"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> додека не се наполни"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 41f5923..d2b2247 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"എല്ലാ അപ്ലിക്കേഷനുകളും നിരസിക്കുക"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ചാർജ്ജുചെയ്‌തു"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ചാർജ്ജുചെയ്യുന്നു"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 8f81367..4982f10 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Бүх програмыг арилгах"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Цэнэглэж байна"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"дүүргэхэд <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index bf7c5a6..900890c 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -225,7 +225,7 @@
     <string name="start_dreams" msgid="7219575858348719790">"डेड्रीम"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"इथरनेट"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"विमान मोड"</string>
-    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब"</string>
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटुथ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब (<xliff:g id="NUMBER">%d</xliff:g> डिव्हाइसेस)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब बंद"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"कोणतेही जोडलेले डिव्हाइसेस उपलब्ध नाहीत"</string>
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सर्व अनुप्रयोग डिसमिस करा"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज झाली"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज होत आहे"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण होईपर्यंत"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 5845d59..f3c6e32 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ketepikan semua aplikasi"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengecas"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Lagi <xliff:g id="CHARGING_TIME">%s</xliff:g> untuk penuh"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index c8f4c55..c9db1b1 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်မည်"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"အားသွင်းပြီး"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"အားသွင်းနေ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ပြည်သည့် အထိ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 60e27ee..b2fbd78 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Avvis alle apper"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Lader"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Fulladet om <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 87cbb6f..67a1c30 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सबै अनुप्रयोगहरू खारेज गर्नुहोस्"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज भयो"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हुँदै"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण नभएसम्म"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6786a74..2c2d6ef 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Alle apps sluiten"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Opladen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tot volledig opgeladen"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3f2c7fd..e2ef340 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Zamknij wszystkie aplikacje"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Ładowanie"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do pełnego naładowania"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b5b2650..df1192d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ignorar todas as aplicações"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"A carregar"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até ficar completa"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c914a50..770cabe 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Dispensar todos os apps"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Carregando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até concluir"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index c84b96f..cd3a1c0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Închideți toate aplicațiile"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Se încarcă"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> până la încărcare completă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index cd00556..7f5d352 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Закрыть все приложения"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядка батареи"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до полной зарядки"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 0a54324..5bd1f8d 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -159,7 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
-    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලු මෑත යෙඳුම් අස් කෙරිණි"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලුම මෑත යෙඳුම් අස් කරන ලදි."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්‍රභා කරඇත."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"දැනුම්දීම් ආවරණය."</string>
@@ -281,7 +281,19 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
-    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"සියලු යෙදුම් අස් කරන්න"</string>
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"සියලුම යෙදුම් අස් කරන්න"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"අරෝපිතයි"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ආරෝපණය වෙමින්"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> සම්පූර්ණ වන තෙක්"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9fbd73e4..5183dab 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odmietnuť všetky aplikácie"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíja sa"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Úplné nabitie o <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index e4a2016..2afb65b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Opusti vse aplikacije"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Polnjenje"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napolnjenosti"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f3d7da0..d7ab3a6 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Одбаци све апликације"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Пуњење"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> док се не напуни"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0e9879a..f293649 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ta bort alla appar"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laddar"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tills batteriet är fulladdat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 05cd74a..d7621e9 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ondoa programu zote"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Inachaji"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Imebakisha <xliff:g id="CHARGING_TIME">%s</xliff:g> ijae"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 7556c7b..d861522 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"எல்லா பயன்பாடுகளையும் விலக்கு"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"சார்ஜ் செய்யப்பட்டது"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"சார்ஜாகிறது"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"முழுவதும் சார்ஜாக <xliff:g id="CHARGING_TIME">%s</xliff:g> ஆகும்"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 7704e85..10b3214 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"అన్ని అనువర్తనాలను తీసివేయి"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ఛార్జ్ చేయబడింది"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ఛార్జ్ అవుతోంది"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"పూర్తిగా నిండటానికి <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index d591d0a..1bc9585 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ปิดแอปพลิเคชันทั้งหมด"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"กำลังชาร์จ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"อีก <xliff:g id="CHARGING_TIME">%s</xliff:g> จึงจะเต็ม"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index abe7b53..cee541e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -282,6 +282,12 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"I-dismiss ang lahat ng application"</string>
+    <string name="recents_multistack_add_stack" msgid="5044995965068125420">"+"</string>
+    <string name="recents_multistack_remove_stack" msgid="3014058144068028841">"-"</string>
+    <string name="recents_multistack_resize_stack" msgid="5511174284568497822">"[]"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nagcha-charge"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> hanggang mapuno"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9bcdc27..21f1472 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -144,7 +144,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Kablosuz"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM kart yok."</string>
-    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth İnternet paylaşımı"</string>
+    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Uçak modu."</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Pil yüzdesi: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistem ayarları."</string>
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Tüm uygulamaları kapat"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Şarj oluyor"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Tam şarj olmasına <xliff:g id="CHARGING_TIME">%s</xliff:g> kaldı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 68f7daa..0909eaa 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Закрити всі додатки"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Заряджається"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"До повного зарядження <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index bc3dbc2..1b29477 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"سبھی ایپلیکیشنز کو برخاست کریں"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"چارج ہوگئی"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"چارج ہو رہی ہے"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> مکمل ہونے تک"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 86ad17e..15c84cb 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Barcha ilovalarni olib tashlash"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Batareya quvvati to‘ldi"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Quvvat olmoqda"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>da to‘ladi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 506c60a..20a19a3 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -159,7 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
-    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã loại bỏ tất cả các ứng dụng gần đây."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã bỏ qua tất cả các ứng dụng gần đây."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Bắt đầu <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bóng thông báo."</string>
@@ -281,7 +281,19 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Loại bỏ tất cả các ứng dụng"</string>
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Bỏ qua tất cả các ứng dụng"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Đang sạc"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> cho đến khi đầy"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 4b39f65..0c5c57b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"关闭所有应用"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"正在充电"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"还需<xliff:g id="CHARGING_TIME">%s</xliff:g>充满"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 50d8489..6e6cc1e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -161,7 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
-    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式已關閉。"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式均已關閉。"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"關閉所有應用程式"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後完成充電"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8a50cf9..5329977 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -161,7 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
-    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的使用程式已全部關閉。"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的應用程式已全部關閉。"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
@@ -284,6 +284,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"關閉所有應用程式"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後充飽"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 19e6b49..2a7adb5 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -282,6 +282,18 @@
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ayikwazanga ukuqala i-<xliff:g id="APP">%s</xliff:g>."</string>
     <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Cashisa zonke izinhlelo zokusebenza"</string>
+    <!-- no translation found for recents_multistack_add_stack (5044995965068125420) -->
+    <skip />
+    <!-- no translation found for recents_multistack_remove_stack (3014058144068028841) -->
+    <skip />
+    <!-- no translation found for recents_multistack_resize_stack (5511174284568497822) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kushajiwe"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Iyashaja"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ize igcwale"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a7783fc..4c0cea8 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -30,7 +30,7 @@
     <color name="notification_list_shadow_top">#80000000</color>
     <drawable name="recents_callout_line">#99ffffff</drawable>
     <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
-    <color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
+    <color name="batterymeter_frame_color">#4DFFFFFF</color><!-- 30% white -->
     <color name="batterymeter_charge_color">#FFFFFFFF</color>
     <color name="batterymeter_bolt_color">#FFFFFFFF</color>
     <color name="qs_batterymeter_frame_color">#FF404040</color>
@@ -129,4 +129,5 @@
     <color name="segmented_button_selected">#FFFFFFFF</color>
     <color name="segmented_button_unselected">#B3B0BEC5</color><!-- 70% blue grey 200 -->
     <color name="volume_panel_divider">#1FFFFFFF</color><!-- 12% white -->
+    <color name="light_mode_icon_color">#FF616161</color><!-- grey 700 -->
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 68dc269..aa53a3e 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -40,5 +40,11 @@
     <item type="id" name="notification_power"/>
     <item type="id" name="notification_screenshot"/>
     <item type="id" name="notification_hidden"/>
+
+    <!-- Whether the icon is from a notification for which targetSdk < L -->
+    <item type="id" name="icon_is_pre_L"/>
+
+    <!-- For notification icons for which targetSdk < L, this caches whether the icon is grayscale -->
+    <item type="id" name="icon_is_grayscale" />
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c977db9..6afca8a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -630,10 +630,6 @@
     <string name="quick_settings_done">Done</string>
     <!-- QuickSettings: Control panel: Label for connected device. [CHAR LIMIT=NONE] -->
     <string name="quick_settings_connected">Connected</string>
-    <!-- QuickSettings: Control panel: Label for a connected Wi-Fi access point when the connection is established by a Wi-Fi assistant application. [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_connected_via_wfa">Connected via Wi\u2011Fi assistant</string>
-    <!-- QuickSettings: Control panel: Label for saved device or connection. [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_saved">Saved</string>
     <!-- QuickSettings: Control panel: Label for connecting device. [CHAR LIMIT=NONE] -->
     <string name="quick_settings_connecting">Connecting...</string>
     <!-- QuickSettings: Tethering. [CHAR LIMIT=NONE] -->
@@ -672,6 +668,19 @@
     <!-- Recents: Dismiss all button. [CHAR LIMIT=NONE] -->
     <string name="recents_dismiss_all_message">Dismiss all applications</string>
 
+    <!-- Recents: MultiStack add stack button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack">+</string>
+    <!-- Recents: MultiStack remove stack button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_remove_stack">-</string>
+    <!-- Recents: MultiStack resize stack button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_resize_stack">[]</string>
+    <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
+    <!-- Recents: MultiStack add stack split vertical radio button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack_dialog_split_vertical">Split Vertical</string>
+    <!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string>
+
     <!-- Expanded Status Bar Header: Battery Charged [CHAR LIMIT=40] -->
     <string name="expanded_header_battery_charged">Charged</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index f2b4a69..bf19b8d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -20,7 +20,7 @@
         <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
     </style>
 
-    <style name="RecentsTheme" parent="@android:style/Theme">
+    <style name="RecentsTheme" parent="@android:style/Theme.Material.Light">
         <!-- NoTitle -->
         <item name="android:windowNoTitle">true</item>
         <!-- Misc -->
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 7bdbd0a..f2f087f 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -23,8 +23,12 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.os.BatteryManager;
@@ -56,12 +60,13 @@
     private float mSubpixelSmoothingRight;
     private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
     private float mTextHeight, mWarningTextHeight;
+    private int mIconTint = Color.WHITE;
 
     private int mHeight;
     private int mWidth;
     private String mWarningString;
     private final int mCriticalLevel;
-    private final int mChargeColor;
+    private int mChargeColor;
     private final float[] mBoltPoints;
     private final Path mBoltPath = new Path();
 
@@ -292,11 +297,27 @@
         for (int i=0; i<mColors.length; i+=2) {
             thresh = mColors[i];
             color = mColors[i+1];
-            if (percent <= thresh) return color;
+            if (percent <= thresh) {
+
+                // Respect tinting for "normal" level
+                if (i == mColors.length-2) {
+                    return mIconTint;
+                } else {
+                    return color;
+                }
+            }
         }
         return color;
     }
 
+    public void setIconTint(int tint) {
+        mIconTint = tint;
+        mFramePaint.setColorFilter(new PorterDuffColorFilter(tint, PorterDuff.Mode.SRC_ATOP));
+        mBoltPaint.setColor(tint);
+        mChargeColor = tint;
+        invalidate();
+    }
+
     @Override
     public void draw(Canvas c) {
         BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6df78ac..f3d214f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -489,6 +489,11 @@
         }
 
         @Override
+        public void resetKeyguard() {
+            resetStateLocked();
+        }
+
+        @Override
         public void playTrustedSound() {
             KeyguardViewMediator.this.playTrustedSound();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index 9155102..95ac558 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -190,6 +190,7 @@
         title.setText(item.line1);
         final TextView summary = (TextView) view.findViewById(android.R.id.summary);
         final boolean twoLines = !TextUtils.isEmpty(item.line2);
+        title.setMaxLines(twoLines ? 1 : 2);
         summary.setVisibility(twoLines ? VISIBLE : GONE);
         summary.setText(twoLines ? item.line2 : null);
         view.setMinimumHeight(mContext.getResources() .getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 974235e..4dacacf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -423,7 +423,9 @@
         }
 
         for (TileRecord record : mRecords) {
-            record.tileView.setDual(record.tile.supportsDualTargets());
+            if (record.tileView.setDual(record.tile.supportsDualTargets())) {
+                record.tileView.handleStateChanged(record.tile.getState());
+            }
             if (record.tileView.getVisibility() == GONE) continue;
             final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth;
             final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index bb353d5..16ae6b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -172,7 +172,7 @@
         }
     }
 
-    public void setDual(boolean dual) {
+    public boolean setDual(boolean dual) {
         final boolean changed = dual != mDual;
         mDual = dual;
         if (changed) {
@@ -199,6 +199,7 @@
         setFocusable(!dual);
         mDivider.setVisibility(dual ? VISIBLE : GONE);
         postInvalidate();
+        return changed;
     }
 
     private void setRipple(RippleDrawable tileBackground) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index bd4dbe6..70746c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs.tiles;
 
+import java.util.List;
+
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -24,16 +26,15 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTileView;
 import com.android.systemui.qs.SignalTileView;
-import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPointController.AccessPoint;
 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
 
 /** Quick settings tile: Wifi **/
@@ -282,10 +283,10 @@
         }
 
         @Override
-        public void onAccessPointsChanged(final AccessPoint[] accessPoints) {
-            mAccessPoints = accessPoints;
+        public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
+            mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
             updateItems();
-            if (accessPoints != null && accessPoints.length > 0) {
+            if (accessPoints != null && accessPoints.size() > 0) {
                 fireScanStateChanged(false);
             }
         }
@@ -299,7 +300,7 @@
         public void onDetailItemClick(Item item) {
             if (item == null || item.tag == null) return;
             final AccessPoint ap = (AccessPoint) item.tag;
-            if (!ap.isConnected) {
+            if (!ap.isActive()) {
                 if (mWifiController.connect(ap)) {
                     mHost.collapsePanels();
                 }
@@ -326,16 +327,10 @@
                     final AccessPoint ap = mAccessPoints[i];
                     final Item item = new Item();
                     item.tag = ap;
-                    item.icon = ap.iconId;
-                    item.line1 = ap.ssid;
-                    if (ap.isConnected) {
-                        item.line2 = mContext.getString(ap.isConfigured ?
-                                R.string.quick_settings_connected :
-                                R.string.quick_settings_connected_via_wfa);
-                    } else if (ap.networkId >= 0) {
-                        item.line2 = mContext.getString(R.string.quick_settings_saved);
-                    }
-                    item.overlay = ap.hasSecurity
+                    item.icon = mWifiController.getIcon(ap);
+                    item.line1 = ap.getSsid();
+                    item.line2 = ap.getSummary();
+                    item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
                             ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
                             : null;
                     items[i] = item;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index cfd6b40..192acc6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -39,6 +39,8 @@
             public static final boolean EnableSearchLayout = true;
             // Enables the thumbnail alpha on the front-most task
             public static final boolean EnableThumbnailAlphaOnFrontmost = false;
+            // Enables all system stacks to show up in the same recents stack
+            public static final boolean EnableMultiStackToSingleStack = true;
             // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
             // Enables the simulated task affiliations
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 3c75aac..9dd82fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -24,7 +24,6 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -56,7 +55,6 @@
 import com.android.systemui.recents.views.TaskViewTransform;
 
 import java.util.ArrayList;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -112,6 +110,9 @@
 
         /** Preloads the next task */
         public void run() {
+            // Temporarily skip this if multi stack is enabled
+            if (mConfig.multiStackEnabled) return;
+
             RecentsConfiguration config = RecentsConfiguration.getInstance();
             if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) {
                 RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -362,13 +363,21 @@
     }
 
     void showRelativeAffiliatedTask(boolean showNextTask) {
+        // Return early if there is no focused stack
+        int focusedStackId = mSystemServicesProxy.getFocusedStack();
+        TaskStack focusedStack = null;
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
         loader.preloadTasks(plan, true /* isTopTaskHome */);
-        TaskStack stack = plan.getTaskStack();
+        if (mConfig.multiStackEnabled) {
+            if (focusedStackId < 0) return;
+            focusedStack = plan.getTaskStack(focusedStackId);
+        } else {
+            focusedStack = plan.getAllTaskStacks().get(0);
+        }
 
-        // Return early if there are no tasks
-        if (stack.getTaskCount() == 0) return;
+        // Return early if there are no tasks in the focused stack
+        if (focusedStack.getTaskCount() == 0) return;
 
         ActivityManager.RunningTaskInfo runningTask = mSystemServicesProxy.getTopMostTask();
         // Return early if there is no running task (can't determine affiliated tasks in this case)
@@ -377,7 +386,7 @@
         if (mSystemServicesProxy.isInHomeStack(runningTask.id)) return;
 
         // Find the task in the recents list
-        ArrayList<Task> tasks = stack.getTasks();
+        ArrayList<Task> tasks = focusedStack.getTasks();
         Task toTask = null;
         ActivityOptions launchOpts = null;
         int taskCount = tasks.size();
@@ -399,7 +408,7 @@
                             R.anim.recents_launch_prev_affiliated_task_source);
                 }
                 if (toTaskKey != null) {
-                    toTask = stack.findTaskWithId(toTaskKey.id);
+                    toTask = focusedStack.findTaskWithId(toTaskKey.id);
                 }
                 numAffiliatedTasks = group.getTaskCount();
                 break;
@@ -473,8 +482,9 @@
             // Reload the widget id before we get the task stack bounds
             reloadSearchBarAppWidget(mContext, mSystemServicesProxy);
         }
-        mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
-                (mConfig.hasTransposedNavBar ? mNavBarWidth : 0), mTaskStackBounds);
+        mConfig.getAvailableTaskStackBounds(mWindowRect.width(), mWindowRect.height(),
+                mStatusBarHeight, (mConfig.hasTransposedNavBar ? mNavBarWidth : 0),
+                mTaskStackBounds);
         if (mConfig.isLandscape && mConfig.hasTransposedNavBar) {
             mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
         } else {
@@ -653,8 +663,25 @@
             // Create a new load plan if onPreloadRecents() was never triggered
             sInstanceLoadPlan = loader.createLoadPlan(mContext);
         }
+
+        // Temporarily skip the transition (use a dummy fade) if multi stack is enabled.
+        // For multi-stack we need to figure out where each of the tasks are going.
+        if (mConfig.multiStackEnabled) {
+            loader.preloadTasks(sInstanceLoadPlan, true);
+            ArrayList<TaskStack> stacks = sInstanceLoadPlan.getAllTaskStacks();
+            TaskStack stack = stacks.get(0);
+            mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, true);
+            TaskStackViewLayoutAlgorithm.VisibilityReport stackVr =
+                    mDummyStackView.computeStackVisibilityReport();
+            ActivityOptions opts = getUnknownTransitionActivityOptions();
+            startAlternateRecentsActivity(topTask, opts, true /* fromHome */,
+                    false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
+            return;
+        }
+
         loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome);
-        TaskStack stack = sInstanceLoadPlan.getTaskStack();
+        ArrayList<TaskStack> stacks = sInstanceLoadPlan.getAllTaskStacks();
+        TaskStack stack = stacks.get(0);
 
         // Prepare the dummy stack for the transition
         mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 1833e09..b1ac733 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.ActivityOptions;
+import android.app.Dialog;
 import android.app.SearchManager;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
@@ -43,7 +44,6 @@
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.RecentsTaskLoadPlan;
 import com.android.systemui.recents.model.RecentsTaskLoader;
-import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.DebugOverlayView;
@@ -75,6 +75,9 @@
     View mEmptyView;
     DebugOverlayView mDebugOverlay;
 
+    // MultiStack debug
+    RecentsMultiStackDialog mMultiStackDebugDialog;
+
     // Search AppWidget
     RecentsAppWidgetHost mAppWidgetHost;
     AppWidgetProviderInfo mSearchAppWidgetInfo;
@@ -190,7 +193,8 @@
         }
 
         // Start loading tasks according to the load plan
-        if (plan.getTaskStack() == null) {
+        ArrayList<TaskStack> stacks = plan.getAllTaskStacks();
+        if (stacks.size() == 0) {
             loader.preloadTasks(plan, mConfig.launchedFromHome);
         }
         RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -199,9 +203,7 @@
         loadOpts.numVisibleTaskThumbnails = mConfig.launchedNumVisibleThumbnails;
         loader.loadTasks(this, plan, loadOpts);
 
-        SpaceNode root = plan.getSpaceNode();
-        ArrayList<TaskStack> stacks = root.getStacks();
-        boolean hasTasks = root.hasTasks();
+        boolean hasTasks = plan.hasTasks();
         if (hasTasks) {
             mRecentsView.setTaskStacks(stacks);
         }
@@ -591,6 +593,40 @@
         }
     }
 
+
+    /**** RecentsMultiStackDialog ****/
+
+    private RecentsMultiStackDialog getMultiStackDebugDialog() {
+        if (mMultiStackDebugDialog == null) {
+            mMultiStackDebugDialog = new RecentsMultiStackDialog(getFragmentManager());
+        }
+        return mMultiStackDebugDialog;
+    }
+
+    @Override
+    public void onMultiStackAddStack() {
+        RecentsMultiStackDialog dialog = getMultiStackDebugDialog();
+        dialog.showAddStackDialog();
+    }
+
+    @Override
+    public void onMultiStackResizeStack() {
+        RecentsMultiStackDialog dialog = getMultiStackDebugDialog();
+        dialog.showResizeStackDialog();
+    }
+
+    @Override
+    public void onMultiStackRemoveStack() {
+        RecentsMultiStackDialog dialog = getMultiStackDebugDialog();
+        dialog.showRemoveStackDialog();
+    }
+
+    @Override
+    public void onMultiStackMoveTask(Task t) {
+        RecentsMultiStackDialog dialog = getMultiStackDebugDialog();
+        dialog.showMoveTaskDialog(t);
+    }
+
     /**** RecentsView.RecentsViewCallbacks Implementation ****/
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index bc10a48..1736c77 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -134,6 +134,7 @@
     public boolean fakeShadows;
 
     /** Dev options and global settings */
+    public boolean multiStackEnabled;
     public boolean lockToAppEnabled;
     public boolean developerOptionsEnabled;
     public boolean debugModeEnabled;
@@ -294,6 +295,7 @@
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED) != 0;
         lockToAppEnabled = ssp.getSystemSetting(context,
                 Settings.System.LOCK_TO_APP_ENABLED) != 0;
+        multiStackEnabled = "1".equals(ssp.getSystemProperty("overview.enableMultiStack"));
     }
 
     /** Called when the configuration has changed, and we want to reset any configuration specific
@@ -335,8 +337,8 @@
      * Returns the task stack bounds in the current orientation. These bounds do not account for
      * the system insets.
      */
-    public void getTaskStackBounds(int windowWidth, int windowHeight, int topInset, int rightInset,
-                                   Rect taskStackBounds) {
+    public void getAvailableTaskStackBounds(int windowWidth, int windowHeight, int topInset,
+            int rightInset, Rect taskStackBounds) {
         Rect searchBarBounds = new Rect();
         getSearchBarBounds(windowWidth, windowHeight, topInset, searchBarBounds);
         if (isLandscape && hasTransposedSearchBar) {
@@ -353,7 +355,7 @@
      * the system insets.
      */
     public void getSearchBarBounds(int windowWidth, int windowHeight, int topInset,
-                                   Rect searchBarSpaceBounds) {
+            Rect searchBarSpaceBounds) {
         // Return empty rects if search is not enabled
         int searchBarSize = searchBarSpaceHeightPx;
         if (!Constants.DebugFlags.App.EnableSearchLayout || !hasSearchBarAppWidget()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsMultiStackDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsMultiStackDialog.java
new file mode 100644
index 0000000..fdf9d39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsMultiStackDialog.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.MutableInt;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+import com.android.systemui.R;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.model.Task;
+
+import java.util.List;
+
+/**
+ * A helper for the dialogs that show when multistack debugging is on.
+ */
+public class RecentsMultiStackDialog extends DialogFragment {
+
+    static final String TAG = "RecentsMultiStackDialog";
+
+    public static final int ADD_STACK_DIALOG = 0;
+    public static final int ADD_STACK_PICK_APP_DIALOG = 1;
+    public static final int REMOVE_STACK_DIALOG = 2;
+    public static final int RESIZE_STACK_DIALOG = 3;
+    public static final int RESIZE_STACK_PICK_STACK_DIALOG = 4;
+    public static final int MOVE_TASK_DIALOG = 5;
+
+    FragmentManager mFragmentManager;
+    int mCurrentDialogType;
+    MutableInt mTargetStackIndex = new MutableInt(0);
+    Task mTaskToMove;
+    SparseArray<ActivityManager.StackInfo> mStacks;
+    List<ResolveInfo> mLauncherActivities;
+    Rect mAddStackRect;
+    Intent mAddStackIntent;
+
+    View mAddStackDialogContent;
+
+    public RecentsMultiStackDialog() {}
+
+    public RecentsMultiStackDialog(FragmentManager mgr) {
+        mFragmentManager = mgr;
+    }
+
+    /** Shows the add-stack dialog. */
+    void showAddStackDialog() {
+        mCurrentDialogType = ADD_STACK_DIALOG;
+        show(mFragmentManager, TAG);
+    }
+
+    /** Creates a new add-stack dialog. */
+    private void createAddStackDialog(final Context context, LayoutInflater inflater,
+            AlertDialog.Builder builder, final SystemServicesProxy ssp) {
+        builder.setTitle("Add Stack - Enter new dimensions");
+        mAddStackDialogContent =
+                inflater.inflate(R.layout.recents_multistack_stack_size_dialog, null, false);
+        Rect windowRect = ssp.getWindowRect();
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_left, windowRect.left);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_top, windowRect.top);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_right, windowRect.right);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_bottom, windowRect.bottom);
+        builder.setView(mAddStackDialogContent);
+        builder.setPositiveButton("Add Stack", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                int left = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_left);
+                int top = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_top);
+                int right = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_right);
+                int bottom = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_bottom);
+                if (bottom <= top || right <= left) {
+                    Toast.makeText(context, "Invalid dimensions", Toast.LENGTH_SHORT).show();
+                    dismiss();
+                    return;
+                }
+
+                // Prompt the user for the app to start
+                dismiss();
+                mCurrentDialogType = ADD_STACK_PICK_APP_DIALOG;
+                mAddStackRect = new Rect(left, top, right, bottom);
+                show(mFragmentManager, TAG);
+            }
+        });
+        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                dismiss();
+            }
+        });
+    }
+
+    /** Creates a new add-stack pick-app dialog. */
+    private void createAddStackPickAppDialog(final Context context, LayoutInflater inflater,
+            AlertDialog.Builder builder, final SystemServicesProxy ssp) {
+        mLauncherActivities = ssp.getLauncherApps();
+        mAddStackIntent = null;
+        int activityCount = mLauncherActivities.size();
+        CharSequence[] activityNames = new CharSequence[activityCount];
+        for (int i = 0; i < activityCount; i++) {
+            activityNames[i] = ssp.getActivityLabel(mLauncherActivities.get(i).activityInfo);
+        }
+        builder.setTitle("Add Stack - Pick starting app");
+        builder.setSingleChoiceItems(activityNames, -1,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        ActivityInfo ai = mLauncherActivities.get(which).activityInfo;
+                        mAddStackIntent = new Intent(Intent.ACTION_MAIN);
+                        mAddStackIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+                        mAddStackIntent.setComponent(new ComponentName(ai.packageName, ai.name));
+                    }
+                });
+        builder.setPositiveButton("Add Stack", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                // Display 0 = default display
+                ssp.createNewStack(0, mAddStackRect, mAddStackIntent);
+            }
+        });
+        builder.setNegativeButton("Skip", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                // Display 0 = default display
+                ssp.createNewStack(0, mAddStackRect, null);
+            }
+        });
+    }
+
+    /** Shows the resize-stack dialog. */
+    void showResizeStackDialog() {
+        mCurrentDialogType = RESIZE_STACK_PICK_STACK_DIALOG;
+        show(mFragmentManager, TAG);
+    }
+
+    /** Creates a new resize-stack pick-stack dialog. */
+    private void createResizeStackPickStackDialog(final Context context, LayoutInflater inflater,
+            AlertDialog.Builder builder, final SystemServicesProxy ssp) {
+        mStacks = ssp.getAllStackInfos();
+        mTargetStackIndex.value = -1;
+        CharSequence[] stackNames = getAllStacksDescriptions(mStacks, -1, null);
+        builder.setTitle("Resize Stack - Pick stack");
+        builder.setSingleChoiceItems(stackNames, mTargetStackIndex.value,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mTargetStackIndex.value = which;
+                    }
+                });
+        builder.setPositiveButton("Resize Stack", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                if (mTargetStackIndex.value != -1) {
+                    // Prompt the user for the new dimensions
+                    dismiss();
+                    mCurrentDialogType = RESIZE_STACK_DIALOG;
+                    show(mFragmentManager, TAG);
+                }
+            }
+        });
+        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                dismiss();
+            }
+        });
+    }
+
+    /** Creates a new resize-stack dialog. */
+    private void createResizeStackDialog(final Context context, LayoutInflater inflater,
+            AlertDialog.Builder builder, final SystemServicesProxy ssp) {
+        builder.setTitle("Resize Stack - Enter new dimensions");
+        final ActivityManager.StackInfo stack = mStacks.valueAt(mTargetStackIndex.value);
+        mAddStackDialogContent =
+                inflater.inflate(R.layout.recents_multistack_stack_size_dialog, null, false);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_left, stack.bounds.left);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_top, stack.bounds.top);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_right, stack.bounds.right);
+        setDimensionInEditText(mAddStackDialogContent, R.id.inset_bottom, stack.bounds.bottom);
+        builder.setView(mAddStackDialogContent);
+        builder.setPositiveButton("Resize Stack", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                int left = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_left);
+                int top = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_top);
+                int right = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_right);
+                int bottom = getDimensionFromEditText(mAddStackDialogContent, R.id.inset_bottom);
+                if (bottom <= top || right <= left) {
+                    Toast.makeText(context, "Invalid dimensions", Toast.LENGTH_SHORT).show();
+                    dismiss();
+                    return;
+                }
+                ssp.resizeStack(stack.stackId, new Rect(left, top, right, bottom));
+            }
+        });
+        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                dismiss();
+            }
+        });
+    }
+
+    /** Shows the remove-stack dialog. */
+    void showRemoveStackDialog() {
+        mCurrentDialogType = REMOVE_STACK_DIALOG;
+        show(mFragmentManager, TAG);
+    }
+
+    /** Shows the move-task dialog. */
+    void showMoveTaskDialog(Task task) {
+        mCurrentDialogType = MOVE_TASK_DIALOG;
+        mTaskToMove = task;
+        show(mFragmentManager, TAG);
+    }
+
+    /** Creates a new move-stack dialog. */
+    private void createMoveTaskDialog(final Context context, LayoutInflater inflater,
+                                AlertDialog.Builder builder, final SystemServicesProxy ssp) {
+        mStacks = ssp.getAllStackInfos();
+        mTargetStackIndex.value = -1;
+        CharSequence[] stackNames = getAllStacksDescriptions(mStacks, mTaskToMove.key.stackId,
+                mTargetStackIndex);
+        builder.setTitle("Move Task to Stack");
+        builder.setSingleChoiceItems(stackNames, mTargetStackIndex.value,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mTargetStackIndex.value = which;
+                    }
+                });
+        builder.setPositiveButton("Move Task", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                if (mTargetStackIndex.value != -1) {
+                    ActivityManager.StackInfo toStack = mStacks.valueAt(mTargetStackIndex.value);
+                    if (toStack.stackId != mTaskToMove.key.stackId) {
+                        ssp.moveTaskToStack(mTaskToMove.key.id, toStack.stackId, true);
+                        mTaskToMove.setStackId(toStack.stackId);
+                    }
+                }
+            }
+        });
+        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                dismiss();
+            }
+        });
+    }
+
+    /** Helper to get an integer value from an edit text. */
+    private int getDimensionFromEditText(View container, int id) {
+        String text = ((EditText) container.findViewById(id)).getText().toString();
+        if (text.trim().length() != 0) {
+            return Integer.parseInt(text.trim());
+        }
+        return 0;
+    }
+
+    /** Helper to set an integer value to an edit text. */
+    private void setDimensionInEditText(View container, int id, int value) {
+        ((EditText) container.findViewById(id)).setText("" + value);
+    }
+
+    /** Gets a list of all the stacks. */
+    private CharSequence[] getAllStacksDescriptions(SparseArray<ActivityManager.StackInfo> stacks,
+            int targetStackId, MutableInt indexOfTargetStackId) {
+        int stackCount = stacks.size();
+        CharSequence[] stackNames = new CharSequence[stackCount];
+        for (int i = 0; i < stackCount; i++) {
+            ActivityManager.StackInfo stack = stacks.valueAt(i);
+            Rect b = stack.bounds;
+            String desc = "Stack " + stack.stackId + " / " +
+                    "" + (stack.taskIds.length > 0 ? stack.taskIds.length : "No") + " tasks\n" +
+                    "(" + b.left + ", " + b.top + ")-(" + b.right + ", " + b.bottom + ")\n";
+            stackNames[i] = desc;
+            if (targetStackId != -1 && stack.stackId == targetStackId) {
+                indexOfTargetStackId.value = i;
+            }
+        }
+        return stackNames;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle args) {
+        final Context context = this.getActivity();
+        final SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+        LayoutInflater inflater = getActivity().getLayoutInflater();
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        switch(mCurrentDialogType) {
+            case ADD_STACK_DIALOG:
+                createAddStackDialog(context, inflater, builder, ssp);
+                break;
+            case ADD_STACK_PICK_APP_DIALOG:
+                createAddStackPickAppDialog(context, inflater, builder, ssp);
+                break;
+            case MOVE_TASK_DIALOG:
+                createMoveTaskDialog(context, inflater, builder, ssp);
+                break;
+            case RESIZE_STACK_PICK_STACK_DIALOG:
+                createResizeStackPickStackDialog(context, inflater, builder, ssp);
+                break;
+            case RESIZE_STACK_DIALOG:
+                createResizeStackDialog(context, inflater, builder, ssp);
+                break;
+        }
+        return builder.create();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 237d4f0..72040fe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -20,6 +20,7 @@
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
+import android.app.IActivityContainer;
 import android.app.IActivityManager;
 import android.app.ITaskStackListener;
 import android.app.SearchManager;
@@ -49,10 +50,12 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Pair;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.SurfaceControl;
@@ -64,6 +67,8 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
@@ -228,6 +233,23 @@
         return null;
     }
 
+    /** Returns a list of all the launcher apps sorted by name. */
+    public List<ResolveInfo> getLauncherApps() {
+        if (mPm == null) return new ArrayList<ResolveInfo>();
+
+        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> activities = mPm.queryIntentActivities(mainIntent, 0 /* flags */);
+        Collections.sort(activities, new Comparator<ResolveInfo>() {
+            @Override
+            public int compare(ResolveInfo o1, ResolveInfo o2) {
+                return getActivityLabel(o1.activityInfo).compareTo(
+                        getActivityLabel(o2.activityInfo));
+            }
+        });
+        return activities;
+    }
+
     /** Returns whether the recents is currently running */
     public boolean isRecentsTopMost(ActivityManager.RunningTaskInfo topTask,
             AtomicBoolean isHomeTopMost) {
@@ -250,6 +272,64 @@
         return false;
     }
 
+    /** Create a new stack. */
+    public void createNewStack(int displayId, Rect bounds, Intent activity) {
+        try {
+            IActivityContainer container = mIam.createStackOnDisplay(displayId);
+            if (container != null) {
+                // Resize the stack
+                resizeStack(container.getStackId(), bounds);
+                // Start the new activity on that stack
+                container.startActivity(activity);
+            }
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /** Resizes a stack. */
+    public void resizeStack(int stackId, Rect bounds) {
+        if (mIam == null) return;
+
+        try {
+            mIam.resizeStack(stackId, bounds);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /** Returns the stack info for all stacks. */
+    public SparseArray<ActivityManager.StackInfo> getAllStackInfos() {
+        if (mIam == null) return new SparseArray<ActivityManager.StackInfo>();
+
+        try {
+            SparseArray<ActivityManager.StackInfo> stacks =
+                    new SparseArray<ActivityManager.StackInfo>();
+            List<ActivityManager.StackInfo> infos = mIam.getAllStackInfos();
+            int stackCount = infos.size();
+            for (int i = 0; i < stackCount; i++) {
+                ActivityManager.StackInfo info = infos.get(i);
+                stacks.put(info.stackId, info);
+            }
+            return stacks;
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            return new SparseArray<ActivityManager.StackInfo>();
+        }
+    }
+
+    /** Returns the focused stack id. */
+    public int getFocusedStack() {
+        if (mIam == null) return -1;
+
+        try {
+            return mIam.getFocusedStackId();
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+
     /** Returns whether the specified task is in the home stack */
     public boolean isInHomeStack(int taskId) {
         if (mAm == null) return false;
@@ -313,7 +393,7 @@
         return thumbnail;
     }
 
-    /** Moves a task to the front with the specified activity options */
+    /** Moves a task to the front with the specified activity options. */
     public void moveTaskToFront(int taskId, ActivityOptions opts) {
         if (mAm == null) return;
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
@@ -326,6 +406,18 @@
         }
     }
 
+    /** Moves a task to another stack. */
+    public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+        if (mIam == null) return;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+        try {
+            mIam.moveTaskToStack(taskId, stackId, toTop);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
     /** Removes the task */
     public void removeTask(int taskId) {
         if (mAm == null) return;
@@ -524,6 +616,13 @@
     }
 
     /**
+     * Returns a system property.
+     */
+    public String getSystemProperty(String key) {
+        return SystemProperties.get(key);
+    }
+
+    /**
      * Returns the window rect.
      */
     public Rect getWindowRect() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 3d25c80..788e473 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -20,9 +20,12 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.util.Log;
+import android.util.SparseArray;
+import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 
@@ -60,7 +63,7 @@
     SystemServicesProxy mSystemServicesProxy;
 
     List<ActivityManager.RecentTaskInfo> mRawTasks;
-    TaskStack mStack;
+    SparseArray<TaskStack> mStacks = new SparseArray<>();
     HashMap<Task.ComponentNameKey, ActivityInfoHandle> mActivityInfoCache =
             new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
 
@@ -90,21 +93,28 @@
     synchronized void preloadPlan(RecentsTaskLoader loader, boolean isTopTaskHome) {
         if (DEBUG) Log.d(TAG, "preloadPlan");
 
+        // This activity info cache will be used for both preloadPlan() and executePlan()
         mActivityInfoCache.clear();
-        mStack = new TaskStack();
+
+        // TODO (multi-display): Currently assume the primary display
+        Rect displayBounds = mSystemServicesProxy.getWindowRect();
 
         Resources res = mContext.getResources();
-        ArrayList<Task> loadedTasks = new ArrayList<Task>();
+        SparseArray<ArrayList<Task>> stacksTasks = new SparseArray<>();
         if (mRawTasks == null) {
             preloadRawTasks(isTopTaskHome);
         }
+        int firstStackId = -1;
         int taskCount = mRawTasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
+            if (firstStackId < 0) {
+                firstStackId = t.stackId;
+            }
 
             // Compose the task key
-            Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
-                    t.firstActiveTime, t.lastActiveTime);
+            Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
+                    t.userId, t.firstActiveTime, t.lastActiveTime);
 
             // Get an existing activity info handle if possible
             Task.ComponentNameKey cnKey = taskKey.getComponentNameKey();
@@ -143,14 +153,42 @@
                     iconFilename);
             task.thumbnail = loader.getAndUpdateThumbnail(taskKey, mSystemServicesProxy, false);
             if (DEBUG) Log.d(TAG, "\tthumbnail: " + taskKey + ", " + task.thumbnail);
-            loadedTasks.add(task);
-        }
-        mStack.setTasks(loadedTasks);
-        mStack.createAffiliatedGroupings(mConfig);
 
-        // Assertion
-        if (mStack.getTaskCount() != mRawTasks.size()) {
-            throw new RuntimeException("Loading failed");
+            if (!mConfig.multiStackEnabled ||
+                    Constants.DebugFlags.App.EnableMultiStackToSingleStack) {
+                ArrayList<Task> stackTasks = stacksTasks.get(firstStackId);
+                if (stackTasks == null) {
+                    stackTasks = new ArrayList<Task>();
+                    stacksTasks.put(firstStackId, stackTasks);
+                }
+                stackTasks.add(task);
+            } else {
+                ArrayList<Task> stackTasks = stacksTasks.get(t.stackId);
+                if (stackTasks == null) {
+                    stackTasks = new ArrayList<Task>();
+                    stacksTasks.put(t.stackId, stackTasks);
+                }
+                stackTasks.add(task);
+            }
+        }
+
+        // Initialize the stacks
+        SparseArray<ActivityManager.StackInfo> stackInfos = mSystemServicesProxy.getAllStackInfos();
+        mStacks.clear();
+        int stackCount = stacksTasks.size();
+        for (int i = 0; i < stackCount; i++) {
+            int stackId = stacksTasks.keyAt(i);
+            ActivityManager.StackInfo info = stackInfos.get(stackId);
+            ArrayList<Task> stackTasks = stacksTasks.valueAt(i);
+            TaskStack stack = new TaskStack(stackId);
+            if (Constants.DebugFlags.App.EnableMultiStackToSingleStack) {
+                stack.setBounds(displayBounds, displayBounds);
+            } else {
+                stack.setBounds(info.bounds, displayBounds);
+            }
+            stack.setTasks(stackTasks);
+            stack.createAffiliatedGroupings(mConfig);
+            mStacks.put(stackId, stack);
         }
     }
 
@@ -166,72 +204,93 @@
         Resources res = mContext.getResources();
 
         // Iterate through each of the tasks and load them according to the load conditions.
-        ArrayList<Task> tasks = mStack.getTasks();
-        int taskCount = tasks.size();
-        for (int i = 0; i < taskCount; i++) {
-            ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
-            Task task = tasks.get(i);
-            Task.TaskKey taskKey = task.key;
+        int stackCount = mStacks.size();
+        for (int j = 0; j < stackCount; j++) {
+            ArrayList<Task> tasks = mStacks.valueAt(j).getTasks();
+            int taskCount = tasks.size();
+            for (int i = 0; i < taskCount; i++) {
+                ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
+                Task task = tasks.get(i);
+                Task.TaskKey taskKey = task.key;
 
-            // Get an existing activity info handle if possible
-            Task.ComponentNameKey cnKey = taskKey.getComponentNameKey();
-            ActivityInfoHandle infoHandle;
-            boolean hadCachedActivityInfo = false;
-            if (mActivityInfoCache.containsKey(cnKey)) {
-                infoHandle = mActivityInfoCache.get(cnKey);
-                hadCachedActivityInfo = true;
-            } else {
-                infoHandle = new ActivityInfoHandle();
-            }
-
-            boolean isRunningTask = (task.key.id == opts.runningTaskId);
-            boolean isVisibleTask = i >= (taskCount - opts.numVisibleTasks);
-            boolean isVisibleThumbnail = i >= (taskCount - opts.numVisibleTaskThumbnails);
-
-            // If requested, skip the running task
-            if (opts.onlyLoadPausedActivities && isRunningTask) {
-                continue;
-            }
-
-            if (opts.loadIcons && (isRunningTask || isVisibleTask)) {
-                if (task.activityIcon == null) {
-                    if (DEBUG) Log.d(TAG, "\tLoading icon: " + taskKey);
-                    task.activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription,
-                            mSystemServicesProxy, res, infoHandle, true);
+                // Get an existing activity info handle if possible
+                Task.ComponentNameKey cnKey = taskKey.getComponentNameKey();
+                ActivityInfoHandle infoHandle;
+                boolean hadCachedActivityInfo = false;
+                if (mActivityInfoCache.containsKey(cnKey)) {
+                    infoHandle = mActivityInfoCache.get(cnKey);
+                    hadCachedActivityInfo = true;
+                } else {
+                    infoHandle = new ActivityInfoHandle();
                 }
-            }
-            if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) {
-                if (task.thumbnail == null || isRunningTask) {
-                    if (DEBUG) Log.d(TAG, "\tLoading thumbnail: " + taskKey);
-                    if (mConfig.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) {
-                        task.thumbnail = loader.getAndUpdateThumbnail(taskKey, mSystemServicesProxy,
-                                true);
-                    } else if (mConfig.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) {
-                        loadQueue.addTask(task);
+
+                boolean isRunningTask = (task.key.id == opts.runningTaskId);
+                boolean isVisibleTask = i >= (taskCount - opts.numVisibleTasks);
+                boolean isVisibleThumbnail = i >= (taskCount - opts.numVisibleTaskThumbnails);
+
+                // If requested, skip the running task
+                if (opts.onlyLoadPausedActivities && isRunningTask) {
+                    continue;
+                }
+
+                if (opts.loadIcons && (isRunningTask || isVisibleTask)) {
+                    if (task.activityIcon == null) {
+                        if (DEBUG) Log.d(TAG, "\tLoading icon: " + taskKey);
+                        task.activityIcon = loader.getAndUpdateActivityIcon(taskKey,
+                                t.taskDescription, mSystemServicesProxy, res, infoHandle, true);
                     }
                 }
-            }
+                if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) {
+                    if (task.thumbnail == null || isRunningTask) {
+                        if (DEBUG) Log.d(TAG, "\tLoading thumbnail: " + taskKey);
+                        if (mConfig.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) {
+                            task.thumbnail = loader.getAndUpdateThumbnail(taskKey,
+                                    mSystemServicesProxy, true);
+                        } else if (mConfig.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) {
+                            loadQueue.addTask(task);
+                        }
+                    }
+                }
 
-            // Update the activity info cache
-            if (!hadCachedActivityInfo && infoHandle.info != null) {
-                mActivityInfoCache.put(cnKey, infoHandle);
+                // Update the activity info cache
+                if (!hadCachedActivityInfo && infoHandle.info != null) {
+                    mActivityInfoCache.put(cnKey, infoHandle);
+                }
             }
         }
     }
 
     /**
-     * Composes and returns a TaskStack from the preloaded list of recent tasks.
+     * Returns all TaskStacks from the preloaded list of recent tasks.
      */
-    public TaskStack getTaskStack() {
-        return mStack;
+    public ArrayList<TaskStack> getAllTaskStacks() {
+        ArrayList<TaskStack> stacks = new ArrayList<TaskStack>();
+        int stackCount = mStacks.size();
+        for (int i = 0; i < stackCount; i++) {
+            stacks.add(mStacks.valueAt(i));
+        }
+        // Ensure that we have at least one stack
+        if (stacks.isEmpty()) {
+            stacks.add(new TaskStack());
+        }
+        return stacks;
     }
 
     /**
-     * Composes and returns a SpaceNode from the preloaded list of recent tasks.
+     * Returns a specific TaskStack from the preloaded list of recent tasks.
      */
-    public SpaceNode getSpaceNode() {
-        SpaceNode node = new SpaceNode();
-        node.setStack(mStack);
-        return node;
+    public TaskStack getTaskStack(int stackId) {
+        return mStacks.get(stackId);
+    }
+
+    /** Returns whether there are any tasks in any stacks. */
+    public boolean hasTasks() {
+        int stackCount = mStacks.size();
+        for (int i = 0; i < stackCount; i++) {
+            if (mStacks.valueAt(i).getTaskCount() > 0) {
+                return true;
+            }
+        }
+        return false;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
deleted file mode 100644
index 831698a..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.model;
-
-import android.graphics.Rect;
-
-import java.util.ArrayList;
-
-
-/**
- * The full recents space is partitioned using a BSP into various nodes that define where task
- * stacks should be placed.
- */
-public class SpaceNode {
-    /* BSP node callbacks */
-    public interface SpaceNodeCallbacks {
-        /** Notifies when a node is added */
-        public void onSpaceNodeAdded(SpaceNode node);
-        /** Notifies when a node is measured */
-        public void onSpaceNodeMeasured(SpaceNode node, Rect rect);
-    }
-
-    SpaceNode mStartNode;
-    SpaceNode mEndNode;
-
-    TaskStack mStack;
-
-    public SpaceNode() {
-        // Do nothing
-    }
-
-    /** Sets the current stack for this space node */
-    public void setStack(TaskStack stack) {
-        mStack = stack;
-    }
-
-    /** Returns the task stack (not null if this is a leaf) */
-    TaskStack getStack() {
-        return mStack;
-    }
-
-    /** Returns whether there are any tasks in any stacks below this node. */
-    public boolean hasTasks() {
-        return (mStack.getTaskCount() > 0) ||
-                (mStartNode != null && mStartNode.hasTasks()) ||
-                (mEndNode != null && mEndNode.hasTasks());
-    }
-
-    /** Returns whether this is a leaf node */
-    boolean isLeafNode() {
-        return (mStartNode == null) && (mEndNode == null);
-    }
-
-    /** Returns all the descendent task stacks */
-    private void getStacksRec(ArrayList<TaskStack> stacks) {
-        if (isLeafNode()) {
-            stacks.add(mStack);
-        } else {
-            mStartNode.getStacksRec(stacks);
-            mEndNode.getStacksRec(stacks);
-        }
-    }
-    public ArrayList<TaskStack> getStacks() {
-        ArrayList<TaskStack> stacks = new ArrayList<TaskStack>();
-        getStacksRec(stacks);
-        return stacks;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 55dfe45..0cd55d7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -36,6 +36,9 @@
         public void onTaskDataLoaded();
         /* Notifies when a task has been unbound */
         public void onTaskDataUnloaded();
+
+        /* Notifies when a task's stack id has changed. */
+        public void onMultiStackDebugTaskStackIdChanged();
     }
 
     /** The ComponentNameKey represents the unique primary key for a component
@@ -68,14 +71,17 @@
     public static class TaskKey {
         final ComponentNameKey mComponentNameKey;
         public final int id;
+        public int stackId;
         public final Intent baseIntent;
         public final int userId;
         public long firstActiveTime;
         public long lastActiveTime;
 
-        public TaskKey(int id, Intent intent, int userId, long firstActiveTime, long lastActiveTime) {
+        public TaskKey(int id, int stackId, Intent intent, int userId, long firstActiveTime,
+                long lastActiveTime) {
             mComponentNameKey = new ComponentNameKey(intent.getComponent(), userId);
             this.id = id;
+            this.stackId = stackId;
             this.baseIntent = intent;
             this.userId = userId;
             this.firstActiveTime = firstActiveTime;
@@ -92,18 +98,19 @@
             if (!(o instanceof TaskKey)) {
                 return false;
             }
-            return id == ((TaskKey) o).id
-                    && userId == ((TaskKey) o).userId;
+            TaskKey otherKey = (TaskKey) o;
+            return id == otherKey.id && stackId == otherKey.stackId && userId == otherKey.userId;
         }
 
         @Override
         public int hashCode() {
-            return (id << 5) + userId;
+            return Objects.hash(id, stackId, userId);
         }
 
         @Override
         public String toString() {
             return "Task.Key: " + id + ", "
+                    + "s: " + stackId + ", "
                     + "u: " + userId + ", "
                     + "lat: " + lastActiveTime + ", "
                     + baseIntent.getComponent().getPackageName();
@@ -180,6 +187,14 @@
         this.group = group;
     }
 
+    /** Updates the stack id of this task. */
+    public void setStackId(int stackId) {
+        key.stackId = stackId;
+        if (mCb != null) {
+            mCb.onMultiStackDebugTaskStackIdChanged();
+        }
+    }
+
     /** Notifies the callback listeners that this task has been loaded */
     public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon) {
         this.applicationIcon = applicationIcon;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 7f7eee4..5aaea15 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents.model;
 
 import android.graphics.Color;
+import android.graphics.Rect;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.NamedCounter;
@@ -173,33 +174,38 @@
         public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curTasks);
     }
 
-    /** A pair of indices representing the group and task positions in the stack and group. */
-    public static class GroupTaskIndex {
-        public int groupIndex; // Index in the stack
-        public int taskIndex;  // Index in the group
-
-        public GroupTaskIndex() {}
-
-        public GroupTaskIndex(int gi, int ti) {
-            groupIndex = gi;
-            taskIndex = ti;
-        }
-    }
-
     // The task offset to apply to a task id as a group affiliation
     static final int IndividualTaskIdOffset = 1 << 16;
 
+    public final int id;
+    public final Rect stackBounds = new Rect();
+    public final Rect displayBounds = new Rect();
+
     FilteredTaskList mTaskList = new FilteredTaskList();
     TaskStackCallbacks mCb;
 
     ArrayList<TaskGrouping> mGroups = new ArrayList<TaskGrouping>();
     HashMap<Integer, TaskGrouping> mAffinitiesGroups = new HashMap<Integer, TaskGrouping>();
 
-    /** Sets the callbacks for this task stack */
+    public TaskStack() {
+        this(0);
+    }
+
+    public TaskStack(int stackId) {
+        id = stackId;
+    }
+
+    /** Sets the callbacks for this task stack. */
     public void setCallbacks(TaskStackCallbacks cb) {
         mCb = cb;
     }
 
+    /** Sets the bounds of this stack. */
+    public void setBounds(Rect stackBounds, Rect displayBounds) {
+        this.stackBounds.set(stackBounds);
+        this.displayBounds.set(displayBounds);
+    }
+
     /** Resets this TaskStack. */
     public void reset() {
         mCb = null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 5152150..ea4c4ba 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -29,8 +29,10 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewStub;
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
+import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -40,6 +42,7 @@
 import com.android.systemui.recents.model.TaskStack;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -56,13 +59,22 @@
         public void onAllTaskViewsDismissed();
         public void onExitToHomeAnimationTriggered();
         public void onScreenPinningRequest();
+
+        public void onMultiStackAddStack();
+        public void onMultiStackResizeStack();
+        public void onMultiStackRemoveStack();
+        public void onMultiStackMoveTask(Task t);
     }
 
     RecentsConfiguration mConfig;
     LayoutInflater mInflater;
     DebugOverlayView mDebugOverlay;
+    ViewStub mMultiStackDebugStub;
+    View mMultiStackDebugView;
+    RecentsViewLayoutAlgorithm mLayoutAlgorithm;
 
     ArrayList<TaskStack> mStacks;
+    List<TaskStackView> mTaskStackViews = new ArrayList<>();
     View mSearchBar;
     RecentsViewCallbacks mCb;
 
@@ -82,6 +94,29 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         mConfig = RecentsConfiguration.getInstance();
         mInflater = LayoutInflater.from(context);
+        mLayoutAlgorithm = new RecentsViewLayoutAlgorithm(mConfig);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        if (!mConfig.multiStackEnabled) return;
+
+        mMultiStackDebugStub = (ViewStub) findViewById(R.id.multistack_debug_view_stub);
+        if (mMultiStackDebugView == null) {
+            mMultiStackDebugView = mMultiStackDebugStub.inflate();
+            mMultiStackDebugView.findViewById(R.id.add_stack).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mCb.onMultiStackAddStack();
+                }
+            });
+            mMultiStackDebugView.findViewById(R.id.resize_stack).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mCb.onMultiStackResizeStack();
+                }
+            });
+        }
     }
 
     /** Sets the callbacks */
@@ -98,29 +133,18 @@
     public void setTaskStacks(ArrayList<TaskStack> stacks) {
         int numStacks = stacks.size();
 
-        // Make a list of the stack view children only
-        ArrayList<TaskStackView> stackViews = new ArrayList<TaskStackView>();
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                stackViews.add((TaskStackView) child);
-            }
-        }
-
         // Remove all/extra stack views
         int numTaskStacksToKeep = 0; // Keep no tasks if we are recreating the layout
         if (mConfig.launchedReuseTaskStackViews) {
-            numTaskStacksToKeep = Math.min(childCount, numStacks);
+            numTaskStacksToKeep = Math.min(mTaskStackViews.size(), numStacks);
         }
-        for (int i = stackViews.size() - 1; i >= numTaskStacksToKeep; i--) {
-            removeView(stackViews.get(i));
-            stackViews.remove(i);
+        for (int i = mTaskStackViews.size() - 1; i >= numTaskStacksToKeep; i--) {
+            removeView(mTaskStackViews.remove(i));
         }
 
         // Update the stack views that we are keeping
         for (int i = 0; i < numTaskStacksToKeep; i++) {
-            TaskStackView tsv = stackViews.get(i);
+            TaskStackView tsv = mTaskStackViews.get(i);
             // If onRecentsHidden is not triggered, we need to the stack view again here
             tsv.reset();
             tsv.setStack(stacks.get(i));
@@ -128,47 +152,53 @@
 
         // Add remaining/recreate stack views
         mStacks = stacks;
-        for (int i = stackViews.size(); i < numStacks; i++) {
+        for (int i = mTaskStackViews.size(); i < numStacks; i++) {
             TaskStack stack = stacks.get(i);
             TaskStackView stackView = new TaskStackView(getContext(), stack);
             stackView.setCallbacks(this);
             addView(stackView);
+            mTaskStackViews.add(stackView);
         }
 
         // Enable debug mode drawing on all the stacks if necessary
         if (mConfig.debugModeEnabled) {
-            for (int i = childCount - 1; i >= 0; i--) {
-                View v = getChildAt(i);
-                if (v != mSearchBar) {
-                    TaskStackView stackView = (TaskStackView) v;
-                    stackView.setDebugOverlay(mDebugOverlay);
-                }
+            for (int i = mTaskStackViews.size() - 1; i >= 0; i--) {
+                TaskStackView stackView = mTaskStackViews.get(i);
+                stackView.setDebugOverlay(mDebugOverlay);
             }
         }
 
+        // Bring the debug view to the front
+        if (mMultiStackDebugView != null) {
+            mMultiStackDebugView.bringToFront();
+        }
+
         // Trigger a new layout
         requestLayout();
     }
 
+    /** Gets the list of task views */
+    List<TaskStackView> getTaskStackViews() {
+        return mTaskStackViews;
+    }
+
     /** Launches the focused task from the first stack if possible */
     public boolean launchFocusedTask() {
         // Get the first stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                TaskStack stack = stackView.mStack;
-                // Iterate the stack views and try and find the focused task
-                List<TaskView> taskViews = stackView.getTaskViews();
-                int taskViewCount = taskViews.size();
-                for (int j = 0; j < taskViewCount; j++) {
-                    TaskView tv = taskViews.get(j);
-                    Task task = tv.getTask();
-                    if (tv.isFocusedTask()) {
-                        onTaskViewClicked(stackView, tv, stack, task, false);
-                        return true;
-                    }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            TaskStack stack = stackView.getStack();
+            // Iterate the stack views and try and find the focused task
+            List<TaskView> taskViews = stackView.getTaskViews();
+            int taskViewCount = taskViews.size();
+            for (int j = 0; j < taskViewCount; j++) {
+                TaskView tv = taskViews.get(j);
+                Task task = tv.getTask();
+                if (tv.isFocusedTask()) {
+                    onTaskViewClicked(stackView, tv, stack, task, false);
+                    return true;
                 }
             }
         }
@@ -178,24 +208,22 @@
     /** Launches the task that Recents was launched from, if possible */
     public boolean launchPreviousTask() {
         // Get the first stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                TaskStack stack = stackView.mStack;
-                ArrayList<Task> tasks = stack.getTasks();
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            TaskStack stack = stackView.getStack();
+            ArrayList<Task> tasks = stack.getTasks();
 
-                // Find the launch task in the stack
-                if (!tasks.isEmpty()) {
-                    int taskCount = tasks.size();
-                    for (int j = 0; j < taskCount; j++) {
-                        if (tasks.get(j).isLaunchTarget) {
-                            Task task = tasks.get(j);
-                            TaskView tv = stackView.getChildViewForTask(task);
-                            onTaskViewClicked(stackView, tv, stack, task, false);
-                            return true;
-                        }
+            // Find the launch task in the stack
+            if (!tasks.isEmpty()) {
+                int taskCount = tasks.size();
+                for (int j = 0; j < taskCount; j++) {
+                    if (tasks.get(j).isLaunchTarget) {
+                        Task task = tasks.get(j);
+                        TaskView tv = stackView.getChildViewForTask(task);
+                        onTaskViewClicked(stackView, tv, stack, task, false);
+                        return true;
                     }
                 }
             }
@@ -209,13 +237,11 @@
         // to ensure that it runs
         ctx.postAnimationTrigger.increment();
 
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.startEnterRecentsAnimation(ctx);
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            stackView.startEnterRecentsAnimation(ctx);
         }
         ctx.postAnimationTrigger.decrement();
     }
@@ -225,13 +251,11 @@
         // We have to increment/decrement the post animation trigger in case there are no children
         // to ensure that it runs
         ctx.postAnimationTrigger.increment();
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.startExitToHomeAnimation(ctx);
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            stackView.startExitToHomeAnimation(ctx);
         }
         ctx.postAnimationTrigger.decrement();
 
@@ -287,22 +311,31 @@
         }
 
         Rect taskStackBounds = new Rect();
-        mConfig.getTaskStackBounds(width, height, mConfig.systemInsets.top,
+        mConfig.getAvailableTaskStackBounds(width, height, mConfig.systemInsets.top,
                 mConfig.systemInsets.right, taskStackBounds);
 
-        // Measure each TaskStackView with the full width and height of the window since the 
+        // Measure each TaskStackView with the full width and height of the window since the
         // transition view is a child of that stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar && child.getVisibility() != GONE) {
-                TaskStackView tsv = (TaskStackView) child;
-                // Set the insets to be the top/left inset + search bounds
-                tsv.setStackInsetRect(taskStackBounds);
-                tsv.measure(widthMeasureSpec, heightMeasureSpec);
+        List<TaskStackView> stackViews = getTaskStackViews();
+        List<Rect> stackViewsBounds = mLayoutAlgorithm.computeStackRects(stackViews,
+                taskStackBounds);
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            if (stackView.getVisibility() != GONE) {
+                // We are going to measure the TaskStackView with the whole RecentsView dimensions,
+                // but the actual stack is going to be inset to the bounds calculated by the layout
+                // algorithm
+                stackView.setStackInsetRect(stackViewsBounds.get(i));
+                stackView.measure(widthMeasureSpec, heightMeasureSpec);
             }
         }
 
+        // Measure the multistack debug view
+        if (mMultiStackDebugView != null) {
+            mMultiStackDebugView.measure(width, height);
+        }
+
         setMeasuredDimension(width, height);
     }
 
@@ -322,14 +355,27 @@
 
         // Layout each TaskStackView with the full width and height of the window since the 
         // transition view is a child of that stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar && child.getVisibility() != GONE) {
-                child.layout(left, top, left + child.getMeasuredWidth(),
-                        top + child.getMeasuredHeight());
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            if (stackView.getVisibility() != GONE) {
+                stackView.layout(left, top, left + stackView.getMeasuredWidth(),
+                        top + stackView.getMeasuredHeight());
             }
         }
+
+        // Layout the multistack debug view
+        if (mMultiStackDebugView != null) {
+            Rect taskStackBounds = new Rect();
+            mConfig.getAvailableTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(),
+                    mConfig.systemInsets.top, mConfig.systemInsets.right, taskStackBounds);
+            mMultiStackDebugView.layout(left,
+                    taskStackBounds.bottom - mConfig.systemInsets.bottom -
+                            mMultiStackDebugView.getMeasuredHeight(),
+                    left + mMultiStackDebugView.getMeasuredWidth(),
+                    taskStackBounds.bottom - mConfig.systemInsets.bottom);
+        }
     }
 
     @Override
@@ -343,41 +389,29 @@
     /** Notifies each task view of the user interaction. */
     public void onUserInteraction() {
         // Get the first stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.onUserInteraction();
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            stackView.onUserInteraction();
         }
     }
 
     /** Focuses the next task in the first stack view */
     public void focusNextTask(boolean forward) {
         // Get the first stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.focusNextTask(forward, true);
-                break;
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        if (!stackViews.isEmpty()) {
+            stackViews.get(0).focusNextTask(forward, true);
         }
     }
 
     /** Dismisses the focused task. */
     public void dismissFocusedTask() {
         // Get the first stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.dismissFocusedTask();
-                break;
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        if (!stackViews.isEmpty()) {
+            stackViews.get(0).dismissFocusedTask();
         }
     }
 
@@ -476,9 +510,16 @@
                     }
                 };
             }
-            opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
-                    b, offsetX, offsetY, transform.rect.width(), transform.rect.height(),
-                    sourceView.getHandler(), animStartedListener);
+            if (mConfig.multiStackEnabled) {
+                opts = ActivityOptions.makeCustomAnimation(sourceView.getContext(),
+                        R.anim.recents_from_unknown_enter,
+                        R.anim.recents_from_unknown_exit,
+                        sourceView.getHandler(), animStartedListener);
+            } else {
+                opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
+                        b, offsetX, offsetY, transform.rect.width(), transform.rect.height(),
+                        sourceView.getHandler(), animStartedListener);
+            }
         }
 
         final ActivityOptions launchOpts = opts;
@@ -561,13 +602,11 @@
     /** Final callback after Recents is finally hidden. */
     public void onRecentsHidden() {
         // Notify each task stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.onRecentsHidden();
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            stackView.onRecentsHidden();
         }
     }
 
@@ -599,18 +638,23 @@
         }
     }
 
+    @Override
+    public void onMultiStackMoveTask(Task t) {
+        if (mCb != null) {
+            mCb.onMultiStackMoveTask(t);
+        }
+    }
+
     /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
 
     @Override
     public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
         // Propagate this event down to each task stack view
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                TaskStackView stackView = (TaskStackView) child;
-                stackView.onPackagesChanged(monitor, packageName, userId);
-            }
+        List<TaskStackView> stackViews = getTaskStackViews();
+        int stackCount = stackViews.size();
+        for (int i = 0; i < stackCount; i++) {
+            TaskStackView stackView = stackViews.get(i);
+            stackView.onPackagesChanged(monitor, packageName, userId);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewLayoutAlgorithm.java
new file mode 100644
index 0000000..eea273c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewLayoutAlgorithm.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.graphics.Rect;
+import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.model.TaskStack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* The layout logic for the RecentsView. */
+public class RecentsViewLayoutAlgorithm {
+
+    RecentsConfiguration mConfig;
+
+    public RecentsViewLayoutAlgorithm(RecentsConfiguration config) {
+        mConfig = config;
+    }
+
+    /** Return the relative coordinate given coordinates in another size. */
+    private int getRelativeCoordinate(int availableOffset, int availableSize, int otherCoord, int otherSize) {
+        float relPos = (float) otherCoord / otherSize;
+        return availableOffset + (int) (relPos * availableSize);
+    }
+
+    /**
+     * Computes and returns the bounds that each of the stack views should take up.
+     */
+    List<Rect> computeStackRects(List<TaskStackView> stackViews, Rect availableBounds) {
+        ArrayList<Rect> bounds = new ArrayList<Rect>(stackViews.size());
+        int stackViewsCount = stackViews.size();
+        for (int i = 0; i < stackViewsCount; i++) {
+            TaskStack stack = stackViews.get(i).getStack();
+            Rect sb = stack.stackBounds;
+            Rect db = stack.displayBounds;
+            Rect ab = availableBounds;
+            bounds.add(new Rect(getRelativeCoordinate(ab.left, ab.width(), sb.left, db.width()),
+                    getRelativeCoordinate(ab.top, ab.height(), sb.top, db.height()),
+                    getRelativeCoordinate(ab.left, ab.width(), sb.right, db.width()),
+                    getRelativeCoordinate(ab.top, ab.height(), sb.bottom, db.height())));
+        }
+        return bounds;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 290792a..2318319 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -60,6 +60,8 @@
         public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks);
         public void onTaskStackFilterTriggered();
         public void onTaskStackUnfilterTriggered();
+
+        public void onMultiStackMoveTask(Task t);
     }
 
     RecentsConfiguration mConfig;
@@ -149,6 +151,11 @@
         requestLayout();
     }
 
+    /** Returns the task stack. */
+    TaskStack getStack() {
+        return mStack;
+    }
+
     /** Sets the debug overlay */
     public void setDebugOverlay(DebugOverlayView overlay) {
         mDebugOverlay = overlay;
@@ -625,6 +632,11 @@
         return mTouchHandler.onGenericMotionEvent(ev);
     }
 
+    /** Returns the region that touch gestures can be started in. */
+    Rect getTouchableRegion() {
+        return mTaskStackBounds;
+    }
+
     @Override
     public void computeScroll() {
         mStackScroller.computeScroll();
@@ -1326,6 +1338,13 @@
         }
     }
 
+    @Override
+    public void onMultiStackMoveTask(TaskView tv) {
+        if (mCb != null) {
+            mCb.onMultiStackMoveTask(tv.getTask());
+        }
+    }
+
     /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index ccad2f1..fabc86d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -96,16 +96,6 @@
         }
         return false;
     }
-    /** Bounds the current scroll if necessary, but does not synchronize the stack view with the model. */
-    public boolean boundScrollRaw() {
-        float curScroll = getStackScroll();
-        float newScroll = getBoundedStackScroll(curScroll);
-        if (Float.compare(newScroll, curScroll) != 0) {
-            setStackScrollRaw(newScroll);
-            return true;
-        }
-        return false;
-    }
 
     /** Returns the bounded stack scroll */
     float getBoundedStackScroll(float scroll) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 4a6112c..6cdddc5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -123,6 +123,16 @@
             return false;
         }
 
+        int action = ev.getAction();
+        if (mConfig.multiStackEnabled) {
+            // Check if we are within the bounds of the stack view contents
+            if ((action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
+                if (!mSv.getTouchableRegion().contains((int) ev.getX(), (int) ev.getY())) {
+                    return false;
+                }
+            }
+        }
+
         // Pass through to swipe helper if we are swiping
         mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
         if (mInterceptedBySwipeHelper) {
@@ -131,7 +141,6 @@
 
         boolean wasScrolling = mScroller.isScrolling() ||
                 (mScroller.mScrollAnimator != null && mScroller.mScrollAnimator.isRunning());
-        int action = ev.getAction();
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN: {
                 // Save the touch down info
@@ -198,6 +207,16 @@
             return false;
         }
 
+        int action = ev.getAction();
+        if (mConfig.multiStackEnabled) {
+            // Check if we are within the bounds of the stack view contents
+            if ((action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
+                if (!mSv.getTouchableRegion().contains((int) ev.getX(), (int) ev.getY())) {
+                    return false;
+                }
+            }
+        }
+
         // Pass through to swipe helper if we are swiping
         if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
             return true;
@@ -206,7 +225,6 @@
         // Update the velocity tracker
         initVelocityTrackerIfNotExists();
 
-        int action = ev.getAction();
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN: {
                 // Save the touch down info
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 82120bf..098f2f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -45,6 +45,8 @@
         public void onTaskViewDismissed(TaskView tv);
         public void onTaskViewClipStateChanged(TaskView tv);
         public void onTaskViewFocusChanged(TaskView tv, boolean focused);
+
+        public void onMultiStackMoveTask(TaskView tv);
     }
 
     RecentsConfiguration mConfig;
@@ -457,6 +459,11 @@
             .start();
     }
 
+    /** Enables/disables handling touch on this task view. */
+    void setTouchEnabled(boolean enabled) {
+        setOnClickListener(enabled ? this : null);
+    }
+
     /** Animates this task view if the user does not interact with the stack after a certain time. */
     void startNoUserInteractionAnimation() {
         mHeaderView.startNoUserInteractionAnimation();
@@ -667,6 +674,9 @@
             // Rebind any listeners
             mHeaderView.mApplicationIcon.setOnClickListener(this);
             mHeaderView.mDismissButton.setOnClickListener(this);
+            if (mConfig.multiStackEnabled) {
+                mHeaderView.mMoveTaskButton.setOnClickListener(this);
+            }
             mActionButtonView.setOnClickListener(this);
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
                 if (mConfig.developerOptionsEnabled) {
@@ -687,6 +697,9 @@
             // Unbind any listeners
             mHeaderView.mApplicationIcon.setOnClickListener(null);
             mHeaderView.mDismissButton.setOnClickListener(null);
+            if (mConfig.multiStackEnabled) {
+                mHeaderView.mMoveTaskButton.setOnClickListener(null);
+            }
             mActionButtonView.setOnClickListener(null);
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
                 mHeaderView.mApplicationIcon.setOnLongClickListener(null);
@@ -695,9 +708,9 @@
         mTaskDataLoaded = false;
     }
 
-    /** Enables/disables handling touch on this task view. */
-    void setTouchEnabled(boolean enabled) {
-        setOnClickListener(enabled ? this : null);
+    @Override
+    public void onMultiStackDebugTaskStackIdChanged() {
+        mHeaderView.rebindToTask(mTask);
     }
 
     /**** View.OnClickListener Implementation ****/
@@ -717,6 +730,10 @@
                         }
                     } else if (v == mHeaderView.mDismissButton) {
                         dismissTask();
+                    } else if (v == mHeaderView.mMoveTaskButton) {
+                        if (mCb != null) {
+                            mCb.onMultiStackMoveTask(tv);
+                        }
                     }
                 }
             }, 125);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index e13eed8..b827acc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -56,6 +56,7 @@
     RecentsConfiguration mConfig;
 
     // Header views
+    ImageView mMoveTaskButton;
     ImageView mDismissButton;
     ImageView mApplicationIcon;
     TextView mActivityDescription;
@@ -126,6 +127,10 @@
         mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
         mActivityDescription = (TextView) findViewById(R.id.activity_description);
         mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+        mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
+        if (mConfig.multiStackEnabled) {
+            mMoveTaskButton.setVisibility(View.VISIBLE);
+        }
 
         // Hide the backgrounds if they are ripple drawables
         if (!Constants.DebugFlags.App.EnableTaskFiltering) {
@@ -188,7 +193,10 @@
             mApplicationIcon.setImageDrawable(t.applicationIcon);
         }
         mApplicationIcon.setContentDescription(t.activityLabel);
-        if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
+        // Always update when multi stack debugging is enabled as the stack id can change
+        if (mConfig.multiStackEnabled) {
+            mActivityDescription.setText("[" + t.key.stackId + "] " + t.activityLabel);
+        } else if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
             mActivityDescription.setText(t.activityLabel);
         }
         // Try and apply the system ui tint
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index eaec8fa..a0ea25f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -507,7 +507,6 @@
                 ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
-        mSettingsObserver.onChange(false); // set up
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
                 mSettingsObserver);
@@ -557,6 +556,7 @@
 
         createAndAddWindows();
 
+        mSettingsObserver.onChange(false); // set up
         disable(switches[0], false /* animate */);
         setSystemUiVisibility(switches[1], 0xffffffff);
         topAppWindowChanged(switches[2] != 0);
@@ -773,11 +773,7 @@
         }
 
         if (entry.icon != null) {
-            if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP) {
-                entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
-            } else {
-                entry.icon.setColorFilter(null);
-            }
+            entry.icon.setTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 6310234..7286907 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -17,6 +17,9 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.telephony.SubscriptionInfo;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -55,6 +58,7 @@
     private int mAirplaneContentDescription;
     private String mWifiDescription;
     private ArrayList<PhoneState> mPhoneStates = new ArrayList<PhoneState>();
+    private int mIconTint = Color.WHITE;
 
     ViewGroup mWifiGroup;
     ImageView mVpn, mWifi, mAirplane, mNoSims;
@@ -121,6 +125,7 @@
         }
 
         apply();
+        applyIconTint();
     }
 
     @Override
@@ -187,6 +192,9 @@
         for (int i = 0; i < n; i++) {
             inflatePhoneState(subs.get(i).getSubscriptionId());
         }
+        if (isAttachedToWindow()) {
+            applyIconTint();
+        }
     }
 
     private PhoneState getOrInflateState(int subId) {
@@ -315,6 +323,29 @@
         setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
     }
 
+    public void setIconTint(int tint) {
+        boolean changed = tint != mIconTint;
+        mIconTint = tint;
+        if (changed && isAttachedToWindow()) {
+            applyIconTint();
+        }
+    }
+
+    private void applyIconTint() {
+        setTint(mVpn, mIconTint);
+        setTint(mWifi, mIconTint);
+        setTint(mNoSims, mIconTint);
+        setTint(mAirplane, mIconTint);
+        for (int i = 0; i < mPhoneStates.size(); i++) {
+            mPhoneStates.get(i).setIconTint(mIconTint);
+        }
+    }
+
+    private void setTint(ImageView v, int tint) {
+        v.setImageTintMode(PorterDuff.Mode.SRC_ATOP);
+        v.setImageTintList(ColorStateList.valueOf(tint));
+    }
+
     private class PhoneState {
         private final int mSubId;
         private boolean mMobileVisible = false;
@@ -369,6 +400,11 @@
                 event.getText().add(mMobileGroup.getContentDescription());
             }
         }
+
+        public void setIconTint(int tint) {
+            setTint(mMobile, tint);
+            setTint(mMobileType, tint);
+        }
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 20dd3e7..d02cd17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -147,6 +147,9 @@
     }
 
     private boolean updateDrawable(boolean withClear) {
+        if (mIcon == null) {
+            return false;
+        }
         Drawable drawable = getIcon(mIcon);
         if (drawable == null) {
             Log.w(TAG, "No icon for slot " + mSlot);
@@ -226,6 +229,12 @@
     }
 
     @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+        updateDrawable();
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index fc4d7fe..262d955 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -22,6 +22,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardHostView;
@@ -85,6 +86,7 @@
             mKeyguardView.onResume();
             mKeyguardView.startAppearAnimation();
             mShowingSoon = false;
+            mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
     };
 
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 a2ff64a..7513fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -112,6 +112,7 @@
     private boolean mQsFullyExpanded;
     private boolean mKeyguardShowing;
     private boolean mDozing;
+    private boolean mDozingOnDown;
     private int mStatusBarState;
     private float mInitialHeightOnTouch;
     private float mInitialTouchX;
@@ -148,7 +149,8 @@
 
     private boolean mBlockTouches;
     private int mNotificationScrimWaitDistance;
-    private boolean mTwoFingerQsExpand;
+    // Used for two finger gesture as well as accessibility shortcut to QS.
+    private boolean mQsExpandImmediate;
     private boolean mTwoFingerQsExpandPossible;
 
     /**
@@ -162,7 +164,7 @@
     private Runnable mLaunchAnimationEndRunnable;
     private boolean mOnlyAffordanceInThisMotion;
     private boolean mKeyguardStatusViewAnimating;
-    private boolean mHeaderAnimatingIn;
+    private boolean mHeaderAnimating;
     private ObjectAnimator mQsContainerAnimator;
     private ValueAnimator mQsSizeChangeAnimator;
 
@@ -221,9 +223,8 @@
         // recompute internal state when qspanel height changes
         mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
-            public void onLayoutChange(View v, int left, int top, int right,
-                    int bottom, int oldLeft, int oldTop, int oldRight,
-                    int oldBottom) {
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
                 final int height = bottom - top;
                 final int oldHeight = oldBottom - oldTop;
                 if (height != oldHeight) {
@@ -475,6 +476,13 @@
         }
     }
 
+    public void expandWithQs() {
+        if (mQsExpansionEnabled) {
+            mQsExpandImmediate = true;
+        }
+        expand();
+    }
+
     @Override
     public void fling(float vel, boolean expand) {
         GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
@@ -500,7 +508,7 @@
         if (mBlockTouches) {
             return false;
         }
-        resetDownStates(event);
+        initDownStates(event);
         int pointerIndex = event.findPointerIndex(mTrackingPointer);
         if (pointerIndex < 0) {
             pointerIndex = 0;
@@ -586,10 +594,11 @@
                 && x < stackScrollerX + mNotificationStackScroller.getWidth();
     }
 
-    private void resetDownStates(MotionEvent event) {
+    private void initDownStates(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
             mOnlyAffordanceInThisMotion = false;
             mQsTouchAboveFalsingThreshold = mQsFullyExpanded;
+            mDozingOnDown = isDozing();
         }
     }
 
@@ -634,7 +643,7 @@
         if (mBlockTouches) {
             return false;
         }
-        resetDownStates(event);
+        initDownStates(event);
         if ((!mIsExpanding || mHintAnimationRunning)
                 && !mQsExpanded
                 && mStatusBar.getBarState() != StatusBarState.SHADE) {
@@ -658,7 +667,7 @@
         if (mExpandedHeight != 0) {
             handleQsDown(event);
         }
-        if (!mTwoFingerQsExpand && mQsTracking) {
+        if (!mQsExpandImmediate && mQsTracking) {
             onQsTouch(event);
             if (!mConflictingQsExpansionGesture) {
                 return true;
@@ -675,7 +684,7 @@
         if (mTwoFingerQsExpandPossible && event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
                 && event.getPointerCount() == 2
                 && event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
-            mTwoFingerQsExpand = true;
+            mQsExpandImmediate = true;
             requestPanelHeightUpdate();
 
             // Normally, we start listening when the panel is expanded, but here we need to start
@@ -865,26 +874,28 @@
 
     public void setBarState(int statusBarState, boolean keyguardFadingAway,
             boolean goingToFullShade) {
-        boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD
-                || statusBarState == StatusBarState.SHADE_LOCKED;
-        if (!mKeyguardShowing && keyguardShowing) {
-            setQsTranslation(mQsExpansionHeight);
-            mHeader.setTranslationY(0f);
-        }
+        int oldState = mStatusBarState;
+        boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
         setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
         setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
-        if (goingToFullShade) {
+
+        mStatusBarState = statusBarState;
+        mKeyguardShowing = keyguardShowing;
+
+        if (goingToFullShade || (oldState == StatusBarState.KEYGUARD
+                && statusBarState == StatusBarState.SHADE_LOCKED)) {
             animateKeyguardStatusBarOut();
+            animateHeaderSlidingIn();
+        } else if (oldState == StatusBarState.SHADE_LOCKED
+                && statusBarState == StatusBarState.KEYGUARD) {
+            animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            animateHeaderSlidingOut();
         } else {
             mKeyguardStatusBar.setAlpha(1f);
             mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
         }
-        mStatusBarState = statusBarState;
-        mKeyguardShowing = keyguardShowing;
+
         updateQsState();
-        if (goingToFullShade) {
-            animateHeaderSlidingIn();
-        }
     }
 
     private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = new Runnable() {
@@ -906,7 +917,7 @@
             = new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
-            mHeaderAnimatingIn = false;
+            mHeaderAnimating = false;
             mQsContainerAnimator = null;
             mQsContainer.removeOnLayoutChangeListener(mQsContainerAnimatorUpdater);
         }
@@ -934,10 +945,13 @@
         @Override
         public boolean onPreDraw() {
             getViewTreeObserver().removeOnPreDrawListener(this);
+            long delay = mStatusBarState == StatusBarState.SHADE_LOCKED
+                    ? 0
+                    : mStatusBar.calculateGoingToFullShadeDelay();
             mHeader.setTranslationY(-mHeader.getCollapsedHeight() - mQsPeekHeight);
             mHeader.animate()
                     .translationY(0f)
-                    .setStartDelay(mStatusBar.calculateGoingToFullShadeDelay())
+                    .setStartDelay(delay)
                     .setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
                     .setInterpolator(mFastOutSlowInInterpolator)
                     .start();
@@ -946,7 +960,7 @@
                     mQsContainer.getTranslationY(),
                     mHeader.getCollapsedHeight() + mQsPeekHeight - mQsContainer.getHeight()
                             - mQsContainer.getTop());
-            mQsContainerAnimator.setStartDelay(mStatusBar.calculateGoingToFullShadeDelay());
+            mQsContainerAnimator.setStartDelay(delay);
             mQsContainerAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
             mQsContainerAnimator.setInterpolator(mFastOutSlowInInterpolator);
             mQsContainerAnimator.addListener(mAnimateHeaderSlidingInListener);
@@ -955,11 +969,33 @@
             return true;
         }
     };
-    
-    private void animateHeaderSlidingIn() {
-        mHeaderAnimatingIn = true;
-        getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
 
+    private void animateHeaderSlidingIn() {
+        mHeaderAnimating = true;
+        getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
+    }
+
+    private void animateHeaderSlidingOut() {
+        mHeaderAnimating = true;
+        mHeader.animate().y(-mHeader.getHeight())
+                .setStartDelay(0)
+                .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
+                .setInterpolator(mFastOutSlowInInterpolator)
+                .setListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mHeader.animate().setListener(null);
+                        mHeaderAnimating = false;
+                        updateQsState();
+                    }
+                })
+                .start();
+        mQsContainer.animate()
+                .y(-mQsContainer.getHeight())
+                .setStartDelay(0)
+                .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
+                .setInterpolator(mFastOutSlowInInterpolator)
+                .start();
     }
 
     private final Runnable mAnimateKeyguardStatusBarInvisibleEndRunnable = new Runnable() {
@@ -974,8 +1010,12 @@
     private void animateKeyguardStatusBarOut() {
         mKeyguardStatusBar.animate()
                 .alpha(0f)
-                .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
-                .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2)
+                .setStartDelay(mStatusBar.isKeyguardFadingAway()
+                        ? mStatusBar.getKeyguardFadingAwayDelay()
+                        : 0)
+                .setDuration(mStatusBar.isKeyguardFadingAway()
+                        ? mStatusBar.getKeyguardFadingAwayDuration() / 2
+                        : StackStateAnimator.ANIMATION_DURATION_STANDARD)
                 .setInterpolator(PhoneStatusBar.ALPHA_OUT)
                 .setUpdateListener(mStatusBarAnimateAlphaListener)
                 .withEndAction(mAnimateKeyguardStatusBarInvisibleEndRunnable)
@@ -990,13 +1030,13 @@
         }
     };
 
-    private void animateKeyguardStatusBarIn() {
+    private void animateKeyguardStatusBarIn(long duration) {
         mKeyguardStatusBar.setVisibility(View.VISIBLE);
         mKeyguardStatusBar.setAlpha(0f);
         mKeyguardStatusBar.animate()
                 .alpha(1f)
                 .setStartDelay(0)
-                .setDuration(DOZE_ANIMATION_DURATION)
+                .setDuration(duration)
                 .setInterpolator(mDozeAnimationInterpolator)
                 .setUpdateListener(mStatusBarAnimateAlphaListener)
                 .start();
@@ -1076,9 +1116,12 @@
     }
 
     private void updateQsState() {
-        boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling;
-        mHeader.setVisibility((mQsExpanded || !mKeyguardShowing) ? View.VISIBLE : View.INVISIBLE);
-        mHeader.setExpanded(mKeyguardShowing || (mQsExpanded && !mStackScrollerOverscrolling));
+        boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling || mHeaderAnimating;
+        mHeader.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
+                ? View.VISIBLE
+                : View.INVISIBLE);
+        mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating)
+                || (mQsExpanded && !mStackScrollerOverscrolling));
         mNotificationStackScroller.setScrollingEnabled(
                 mStatusBarState != StatusBarState.KEYGUARD && (!mQsExpanded
                         || mQsExpansionFromOverscroll));
@@ -1116,6 +1159,10 @@
         if (mKeyguardShowing) {
             updateHeaderKeyguard();
         }
+        if (mStatusBarState == StatusBarState.SHADE_LOCKED
+                || mStatusBarState == StatusBarState.KEYGUARD) {
+            updateKeyguardBottomAreaAlpha();
+        }
         if (mStatusBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled) {
             mQsNavbarScrim.setAlpha(getQsExpansionFraction());
@@ -1156,17 +1203,17 @@
     }
 
     private void setQsTranslation(float height) {
-        if (!mHeaderAnimatingIn) {
+        if (!mHeaderAnimating) {
             mQsContainer.setY(height - mQsContainer.getDesiredHeight() + getHeaderTranslation());
         }
-        if (mKeyguardShowing) {
+        if (mKeyguardShowing && !mHeaderAnimating) {
             mHeader.setY(interpolate(getQsExpansionFraction(), -mHeader.getHeight(), 0));
         }
     }
 
     private float calculateQsTopPadding() {
         if (mKeyguardShowing
-                && (mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted)) {
+                && (mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted)) {
 
             // Either QS pushes the notifications down when fully expanded, or QS is fully above the
             // notifications (mostly on tablets). maxNotifications denotes the normal top padding
@@ -1200,7 +1247,7 @@
                 mScrollView.getScrollY(),
                 mAnimateNextTopPaddingChange || animate,
                 mKeyguardShowing
-                        && (mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted));
+                        && (mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted));
         mAnimateNextTopPaddingChange = false;
     }
 
@@ -1313,7 +1360,7 @@
             min = Math.max(min, minHeight);
         }
         int maxHeight;
-        if (mTwoFingerQsExpand || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted) {
+        if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted) {
             maxHeight = calculatePanelHeightQsExpanded();
         } else {
             maxHeight = calculatePanelHeightShade();
@@ -1328,10 +1375,10 @@
 
     @Override
     protected void onHeightUpdated(float expandedHeight) {
-        if (!mQsExpanded || mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted) {
+        if (!mQsExpanded || mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted) {
             positionClockAndNotifications();
         }
-        if (mTwoFingerQsExpand || mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
+        if (mQsExpandImmediate || mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
                 && !mQsExpansionFromOverscroll) {
             float t;
             if (mKeyguardShowing) {
@@ -1471,8 +1518,7 @@
      * Hides the header when notifications are colliding with it.
      */
     private void updateHeader() {
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
-                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
             updateHeaderKeyguard();
         } else {
             updateHeaderShade();
@@ -1481,15 +1527,14 @@
     }
 
     private void updateHeaderShade() {
-        if (!mHeaderAnimatingIn) {
+        if (!mHeaderAnimating) {
             mHeader.setTranslationY(getHeaderTranslation());
         }
         setQsTranslation(mQsExpansionHeight);
     }
 
     private float getHeaderTranslation() {
-        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
-                || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+        if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
             return 0;
         }
         if (mNotificationStackScroller.getNotGoneChildCount() == 0) {
@@ -1502,30 +1547,42 @@
         return Math.min(0, mNotificationStackScroller.getTranslationY()) / HEADER_RUBBERBAND_FACTOR;
     }
 
-    private void updateHeaderKeyguard() {
-        float alphaNotifications;
+    /**
+     * @return the alpha to be used to fade out the contents on Keyguard (status bar, bottom area)
+     *         during swiping up
+     */
+    private float getKeyguardContentsAlpha() {
+        float alpha;
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
 
             // When on Keyguard, we hide the header as soon as the top card of the notification
             // stack scroller is close enough (collision distance) to the bottom of the header.
-            alphaNotifications = getNotificationsTopY()
+            alpha = getNotificationsTopY()
                     /
                     (mKeyguardStatusBar.getHeight() + mNotificationsHeaderCollideDistance);
         } else {
 
             // In SHADE_LOCKED, the top card is already really close to the header. Hide it as
             // soon as we start translating the stack.
-            alphaNotifications = getNotificationsTopY() / mKeyguardStatusBar.getHeight();
+            alpha = getNotificationsTopY() / mKeyguardStatusBar.getHeight();
         }
-        alphaNotifications = MathUtils.constrain(alphaNotifications, 0, 1);
-        alphaNotifications = (float) Math.pow(alphaNotifications, 0.75);
+        alpha = MathUtils.constrain(alpha, 0, 1);
+        alpha = (float) Math.pow(alpha, 0.75);
+        return alpha;
+    }
+
+    private void updateHeaderKeyguard() {
         float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
-        mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion)
+        mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
                 * mKeyguardStatusBarAnimateAlpha);
-        mKeyguardBottomArea.setAlpha(Math.min(1 - getQsExpansionFraction(), alphaNotifications));
         setQsTranslation(mQsExpansionHeight);
     }
 
+    private void updateKeyguardBottomAreaAlpha() {
+        mKeyguardBottomArea.setAlpha(
+                Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction()));
+    }
+
     private float getNotificationsTopY() {
         if (mNotificationStackScroller.getNotGoneChildCount() == 0) {
             return getExpandedHeight();
@@ -1555,7 +1612,7 @@
         } else {
             setListening(true);
         }
-        mTwoFingerQsExpand = false;
+        mQsExpandImmediate = false;
         mTwoFingerQsExpandPossible = false;
     }
 
@@ -1573,7 +1630,7 @@
 
     @Override
     protected void setOverExpansion(float overExpansion, boolean isPixels) {
-        if (mConflictingQsExpansionGesture || mTwoFingerQsExpand) {
+        if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
             return;
         }
         if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
@@ -1593,7 +1650,7 @@
     protected void onTrackingStarted() {
         super.onTrackingStarted();
         if (mQsFullyExpanded) {
-            mTwoFingerQsExpand = true;
+            mQsExpandImmediate = true;
         }
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
@@ -1756,6 +1813,7 @@
         mSecureCameraLaunchManager.onSwipingStarted();
         requestDisallowInterceptTouchEvent(true);
         mOnlyAffordanceInThisMotion = true;
+        mQsTracking = false;
     }
 
     @Override
@@ -1817,7 +1875,7 @@
     @Override
     protected boolean fullyExpandedClearAllVisible() {
         return mNotificationStackScroller.isDismissViewNotGone()
-                && mNotificationStackScroller.isScrolledToBottom() && !mTwoFingerQsExpand;
+                && mNotificationStackScroller.isScrolledToBottom() && !mQsExpandImmediate;
     }
 
     @Override
@@ -1897,7 +1955,7 @@
             mKeyguardBottomArea.setVisibility(View.VISIBLE);
             mKeyguardStatusBar.setVisibility(View.VISIBLE);
             if (animate) {
-                animateKeyguardStatusBarIn();
+                animateKeyguardStatusBarIn(DOZE_ANIMATION_DURATION);
                 mKeyguardBottomArea.startFinishDozeAnimation();
             }
         }
@@ -1947,6 +2005,32 @@
         onEmptySpaceClick(x);
     }
 
+    protected boolean onMiddleClicked() {
+        switch (mStatusBar.getBarState()) {
+            case StatusBarState.KEYGUARD:
+                if (!mDozingOnDown) {
+                    EventLogTags.writeSysuiLockscreenGesture(
+                            EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT,
+                            0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+                    startUnlockHintAnimation();
+                }
+                return true;
+            case StatusBarState.SHADE_LOCKED:
+                if (!mQsExpanded) {
+                    mStatusBar.goToKeyguard();
+                }
+                return true;
+            case StatusBarState.SHADE:
+
+                // This gets called in the middle of the touch handling, where the state is still
+                // that we are tracking the panel. Collapse the panel after this is done.
+                post(mPostCollapseRunnable);
+                return false;
+            default:
+                return true;
+        }
+    }
+
     @Override
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index d86ccee..47034e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -100,7 +100,6 @@
     private boolean mCollapseAfterPeek;
     private boolean mExpanding;
     private boolean mGestureWaitForTouchSlop;
-    private boolean mDozingOnDown;
     private Runnable mPeekRunnable = new Runnable() {
         @Override
         public void run() {
@@ -247,7 +246,6 @@
                 mUpdateFlingOnLayout = false;
                 mPeekTouching = mPanelClosedOnDown;
                 mTouchAboveFalsingThreshold = false;
-                mDozingOnDown = isDozing();
                 if (mVelocityTracker == null) {
                     initVelocityTracker();
                 }
@@ -431,7 +429,6 @@
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
                 mTouchAboveFalsingThreshold = false;
-                mDozingOnDown = isDozing();
                 initVelocityTracker();
                 trackMovement(event);
                 break;
@@ -942,35 +939,14 @@
         }
     }
 
-    private final Runnable mPostCollapseRunnable = new Runnable() {
+    protected final Runnable mPostCollapseRunnable = new Runnable() {
         @Override
         public void run() {
             collapse(false /* delayed */);
         }
     };
-    private boolean onMiddleClicked() {
-        switch (mStatusBar.getBarState()) {
-            case StatusBarState.KEYGUARD:
-                if (!mDozingOnDown) {
-                    EventLogTags.writeSysuiLockscreenGesture(
-                            EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT,
-                            0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
-                    startUnlockHintAnimation();
-                }
-                return true;
-            case StatusBarState.SHADE_LOCKED:
-                mStatusBar.goToKeyguard();
-                return true;
-            case StatusBarState.SHADE:
 
-                // This gets called in the middle of the touch handling, where the state is still
-                // that we are tracking the panel. Collapse the panel after this is done.
-                post(mPostCollapseRunnable);
-                return false;
-            default:
-                return true;
-        }
-    }
+    protected abstract boolean onMiddleClicked();
 
     protected abstract void onEdgeClicked(boolean right);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 25a2f93..3ee7fb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -32,7 +32,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeInterpolator;
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -50,6 +49,7 @@
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -82,14 +82,12 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Display;
 import android.view.Gravity;
-import android.view.HardwareCanvas;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -97,23 +95,17 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
-import android.view.ViewPropertyAnimator;
 import android.view.ViewStub;
-import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AccelerateInterpolator;
-import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.view.animation.PathInterpolator;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
@@ -172,7 +164,6 @@
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
-import com.android.systemui.statusbar.stack.StackScrollAlgorithm;
 import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
 import com.android.systemui.volume.VolumeComponent;
 
@@ -212,9 +203,6 @@
 
     private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
 
-    private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService
-    private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
-
     private static final int STATUS_OR_NAV_TRANSIENT =
             View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
     private static final long AUTOHIDE_TIMEOUT_MS = 3000;
@@ -238,6 +226,8 @@
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
 
+    private int mLightModeIconColor;
+
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -261,8 +251,7 @@
     AccessibilityController mAccessibilityController;
 
     int mNaturalBarHeight = -1;
-    int mIconSize = -1;
-    int mIconHPadding = -1;
+
     Display mDisplay;
     Point mCurrentDisplaySize = new Point();
 
@@ -278,23 +267,7 @@
     int mPixelFormat;
     Object mQueueLock = new Object();
 
-    // viewgroup containing the normal contents of the statusbar
-    LinearLayout mStatusBarContents;
-
-    // right-hand icons
-    LinearLayout mSystemIconArea;
-    LinearLayout mSystemIcons;
-
-    // left-hand icons
-    LinearLayout mStatusIcons;
-    LinearLayout mStatusIconsKeyguard;
-
-    // the icons themselves
-    IconMerger mNotificationIcons;
-    View mNotificationIconArea;
-
-    // [+>
-    View mMoreIcon;
+    StatusBarIconController mIconController;
 
     // expanded notifications
     NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -419,7 +392,6 @@
     private boolean mDozing;
     private boolean mScrimSrcModeEnabled;
 
-    private Interpolator mLinearOutSlowIn;
     private Interpolator mLinearInterpolator = new LinearInterpolator();
     private Interpolator mBackdropInterpolator = new AccelerateDecelerateInterpolator();
     public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
@@ -562,6 +534,9 @@
         updateDisplaySize();
         mScrimSrcModeEnabled = mContext.getResources().getBoolean(
                 R.bool.config_status_bar_scrim_behind_use_src);
+        mLightModeIconColor = mContext.getResources().getColor(R.color.light_mode_icon_color,
+                mContext.getTheme());
+
         super.start(); // calls createAndAddWindows()
 
         mMediaSessionManager
@@ -610,8 +585,6 @@
         updateDisplaySize(); // populates mDisplayMetrics
         updateResources();
 
-        mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
-
         mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
                 R.layout.super_status_bar, null);
         mStatusBarWindow.mService = this;
@@ -689,15 +662,6 @@
         // figure out which pixel-format to use for the status bar.
         mPixelFormat = PixelFormat.OPAQUE;
 
-        mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
-        mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons);
-        mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
-        mNotificationIconArea = mStatusBarView.findViewById(R.id.notification_icon_area_inner);
-        mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
-        mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
-        mNotificationIcons.setOverflowIndicator(mMoreIcon);
-        mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
-
         mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                 R.id.notification_stack_scroller);
         mStackScroller.setLongPressListener(getNotificationLongClicker());
@@ -741,7 +705,6 @@
         mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
         mHeader.setActivityStarter(this);
         mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
-        mStatusIconsKeyguard = (LinearLayout) mKeyguardStatusBar.findViewById(R.id.statusIcons);
         mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
         mKeyguardBottomArea =
                 (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
@@ -756,6 +719,9 @@
         // set the inital view visibility
         setAreThereNotifications();
 
+        mIconController = new StatusBarIconController(
+                mContext, mStatusBarView, mKeyguardStatusBar, this);
+
         // Background thread for any controllers that need it.
         mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
         mHandlerThread.start();
@@ -1177,49 +1143,17 @@
         mWindowManager.removeView(mHeadsUpNotificationView);
     }
 
-    public void refreshAllStatusBarIcons() {
-        refreshAllIconsForLayout(mStatusIcons);
-        refreshAllIconsForLayout(mStatusIconsKeyguard);
-        refreshAllIconsForLayout(mNotificationIcons);
-    }
-
-    private void refreshAllIconsForLayout(LinearLayout ll) {
-        final int count = ll.getChildCount();
-        for (int n = 0; n < count; n++) {
-            View child = ll.getChildAt(n);
-            if (child instanceof StatusBarIconView) {
-                ((StatusBarIconView) child).updateDrawable();
-            }
-        }
-    }
-
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
-        if (SPEW) Log.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
-                + " icon=" + icon);
-        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
-        view.set(icon);
-        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
-                LayoutParams.WRAP_CONTENT, mIconSize));
-        view = new StatusBarIconView(mContext, slot, null);
-        view.set(icon);
-        mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
-                LayoutParams.WRAP_CONTENT, mIconSize));
+        mIconController.addSystemIcon(slot, index, viewIndex, icon);
     }
 
     public void updateIcon(String slot, int index, int viewIndex,
             StatusBarIcon old, StatusBarIcon icon) {
-        if (SPEW) Log.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
-                + " old=" + old + " icon=" + icon);
-        StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
-        view.set(icon);
-        view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
-        view.set(icon);
+        mIconController.updateSystemIcon(slot, index, viewIndex, old, icon);
     }
 
     public void removeIcon(String slot, int index, int viewIndex) {
-        if (SPEW) Log.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
-        mStatusIcons.removeViewAt(viewIndex);
-        mStatusIconsKeyguard.removeViewAt(viewIndex);
+        mIconController.removeSystemIcon(slot, index, viewIndex);
     }
 
     public UserHandle getCurrentUserHandle() {
@@ -1339,7 +1273,6 @@
         if (mNavigationBarView != null) {
             mNavigationBarView.setLayoutDirection(layoutDirection);
         }
-        refreshAllStatusBarIcons();
     }
 
     private void updateShowSearchHoldoff() {
@@ -1480,69 +1413,10 @@
 
     @Override
     protected void updateNotifications() {
-        // TODO: Move this into updateNotificationIcons()?
-        if (mNotificationIcons == null) return;
-
         mNotificationData.filterAndSort();
 
         updateNotificationShade();
-        updateNotificationIcons();
-    }
-
-    private void updateNotificationIcons() {
-        final LinearLayout.LayoutParams params
-            = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
-
-        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
-        final int N = activeNotifications.size();
-        ArrayList<StatusBarIconView> toShow = new ArrayList<>(N);
-
-        // Filter out notifications with low scores.
-        for (int i = 0; i < N; i++) {
-            Entry ent = activeNotifications.get(i);
-            if (ent.notification.getScore() < HIDE_ICONS_BELOW_SCORE &&
-                    !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) {
-                continue;
-            }
-            toShow.add(ent.icon);
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "refreshing icons: " + toShow.size() +
-                    " notifications, mNotificationIcons=" + mNotificationIcons);
-        }
-
-        ArrayList<View> toRemove = new ArrayList<View>();
-        for (int i=0; i<mNotificationIcons.getChildCount(); i++) {
-            View child = mNotificationIcons.getChildAt(i);
-            if (!toShow.contains(child)) {
-                toRemove.add(child);
-            }
-        }
-
-        final int toRemoveCount = toRemove.size();
-        for (int i = 0; i < toRemoveCount; i++) {
-            mNotificationIcons.removeView(toRemove.get(i));
-        }
-
-        for (int i=0; i<toShow.size(); i++) {
-            View v = toShow.get(i);
-            if (v.getParent() == null) {
-                mNotificationIcons.addView(v, i, params);
-            }
-        }
-
-        // Resort notification icons
-        final int childCount = mNotificationIcons.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View actual = mNotificationIcons.getChildAt(i);
-            StatusBarIconView expected = toShow.get(i);
-            if (actual == expected) {
-                continue;
-            }
-            mNotificationIcons.removeView(expected);
-            mNotificationIcons.addView(expected, i);
-        }
+        mIconController.updateNotificationIcons(mNotificationData);
     }
 
     @Override
@@ -1826,14 +1700,6 @@
         }
     }
 
-    public void showClock(boolean show) {
-        if (mStatusBarView == null) return;
-        View clock = mStatusBarView.findViewById(R.id.clock);
-        if (clock != null) {
-            clock.setVisibility(show ? View.VISIBLE : View.GONE);
-        }
-    }
-
     private int adjustDisableFlags(int state) {
         if (!mLaunchTransitionFadingAway
                 && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
@@ -1882,17 +1748,16 @@
         Log.d(TAG, flagdbg.toString());
 
         if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
-            mSystemIconArea.animate().cancel();
             if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
-                animateStatusBarHide(mSystemIconArea, animate);
+                mIconController.hideSystemIconArea(animate);
             } else {
-                animateStatusBarShow(mSystemIconArea, animate);
+                mIconController.showSystemIconArea(animate);
             }
         }
 
         if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
-            boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
-            showClock(show);
+            boolean visible = (state & StatusBarManager.DISABLE_CLOCK) == 0;
+            mIconController.setClockVisibility(visible);
         }
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
@@ -1916,9 +1781,9 @@
 
         if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
-                animateStatusBarHide(mNotificationIconArea, animate);
+                mIconController.hideNotificationIconArea(animate);
             } else {
-                animateStatusBarShow(mNotificationIconArea, animate);
+                mIconController.showNotificationIconArea(animate);
             }
         }
 
@@ -1929,60 +1794,6 @@
         }
     }
 
-    /**
-     * Animates {@code v}, a view that is part of the status bar, out.
-     */
-    private void animateStatusBarHide(final View v, boolean animate) {
-        v.animate().cancel();
-        if (!animate) {
-            v.setAlpha(0f);
-            v.setVisibility(View.INVISIBLE);
-            return;
-        }
-        v.animate()
-                .alpha(0f)
-                .setDuration(160)
-                .setStartDelay(0)
-                .setInterpolator(ALPHA_OUT)
-                .withEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        v.setVisibility(View.INVISIBLE);
-                    }
-                });
-    }
-
-    /**
-     * Animates {@code v}, a view that is part of the status bar, in.
-     */
-    private void animateStatusBarShow(View v, boolean animate) {
-        v.animate().cancel();
-        v.setVisibility(View.VISIBLE);
-        if (!animate) {
-            v.setAlpha(1f);
-            return;
-        }
-        v.animate()
-                .alpha(1f)
-                .setDuration(320)
-                .setInterpolator(ALPHA_IN)
-                .setStartDelay(50)
-
-                // We need to clean up any pending end action from animateStatusBarHide if we call
-                // both hide and show in the same frame before the animation actually gets started.
-                // cancel() doesn't really remove the end action.
-                .withEndAction(null);
-
-        // Synchronize the motion with the Keyguard fading if necessary.
-        if (mKeyguardFadingAway) {
-            v.animate()
-                    .setDuration(mKeyguardFadingAwayDuration)
-                    .setInterpolator(mLinearOutSlowIn)
-                    .setStartDelay(mKeyguardFadingAwayDelay)
-                    .start();
-        }
-    }
-
     @Override
     protected BaseStatusBar.H createHandler() {
         return new PhoneStatusBar.H();
@@ -2206,8 +2017,7 @@
         // Settings are not available in setup
         if (!mUserSetup) return;
 
-        mNotificationPanel.expand();
-        mNotificationPanel.openQs();
+        mNotificationPanel.expandWithQs();
 
         if (false) postStartTracing();
     }
@@ -2419,6 +2229,16 @@
                 mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
             }
 
+            if ((diff & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0 || sbModeChanged) {
+                boolean isTransparentBar = (mStatusBarMode == MODE_TRANSPARENT
+                        || mStatusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
+                boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
+                boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
+
+                mIconController.setIconTint(
+                        (allowLight && light) ? mLightModeIconColor : Color.WHITE);
+
+            }
             // restore the recents bit
             if (wasRecentsVisible) {
                 mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
@@ -2668,12 +2488,7 @@
                 mNotificationData.dump(pw, "  ");
             }
 
-            int N = mStatusIcons.getChildCount();
-            pw.println("  system icons: " + N);
-            for (int i=0; i<N; i++) {
-                StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
-                pw.println("    [" + i + "] icon=" + ic);
-            }
+            mIconController.dump(pw);
 
             if (false) {
                 pw.println("see the logcat for a dump of the views we have created.");
@@ -2716,6 +2531,12 @@
         if (mSecurityController != null) {
             mSecurityController.dump(fd, pw, args);
         }
+        if (mHeadsUpNotificationView != null) {
+            mHeadsUpNotificationView.dump(fd, pw, args);
+        } else {
+            pw.println("  mHeadsUpNotificationView: null");
+        }
+
         pw.println("SharedPreferences:");
         for (Map.Entry<String, ?> entry : mContext.getSharedPreferences(mContext.getPackageName(),
                 Context.MODE_PRIVATE).getAll().entrySet()) {
@@ -2872,10 +2693,10 @@
         updateDisplaySize(); // populates mDisplayMetrics
 
         updateResources();
-        updateClockSize();
         repositionNavigationBar();
         updateShowSearchHoldoff();
         updateRowStates();
+        mIconController.updateResources();
         mScreenPinningRequest.onConfigurationChanged();
     }
 
@@ -2901,8 +2722,7 @@
         mUserSetupObserver.onChange(false);
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true,
-                mUserSetupObserver,
-                mCurrentUserId);
+                mUserSetupObserver, mCurrentUserId);
     }
 
     private void setHeadsUpVisibility(boolean vis) {
@@ -2932,8 +2752,6 @@
         }
 
         loadDimens();
-        mLinearOutSlowIn = AnimationUtils.loadInterpolator(
-                mContext, android.R.interpolator.linear_out_slow_in);
 
         if (mNotificationPanel != null) {
             mNotificationPanel.updateResources();
@@ -2946,31 +2764,12 @@
         }
     }
 
-    private void updateClockSize() {
-        if (mStatusBarView == null) return;
-        TextView clock = (TextView) mStatusBarView.findViewById(R.id.clock);
-        if (clock != null) {
-            FontSizeUtils.updateFontSize(clock, R.dimen.status_bar_clock_size);
-        }
-    }
     protected void loadDimens() {
         final Resources res = mContext.getResources();
 
         mNaturalBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
 
-        int newIconSize = res.getDimensionPixelSize(
-            com.android.internal.R.dimen.status_bar_icon_size);
-        int newIconHPadding = res.getDimensionPixelSize(
-            R.dimen.status_bar_icon_padding);
-
-        if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
-//            Log.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
-            mIconHPadding = newIconHPadding;
-            mIconSize = newIconSize;
-            //reloadAllNotificationIcons(); // reload the tray
-        }
-
         mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
 
         mHeadsUpNotificationDecay = res.getInteger(R.integer.heads_up_notification_decay);
@@ -3179,7 +2978,6 @@
 
     private boolean mDemoModeAllowed;
     private boolean mDemoMode;
-    private DemoStatusIcons mDemoStatusIcons;
 
     @Override
     public void dispatchDemoCommand(String command, Bundle args) {
@@ -3208,10 +3006,8 @@
             dispatchDemoCommandToView(command, args, R.id.battery);
         }
         if (modeChange || command.equals(COMMAND_STATUS)) {
-            if (mDemoStatusIcons == null) {
-                mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize);
-            }
-            mDemoStatusIcons.dispatchDemoCommand(command, args);
+            mIconController.dispatchDemoCommand(command, args);
+
         }
         if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) {
             mNetworkController.dispatchDemoCommand(command, args);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
new file mode 100644
index 0000000..5622993
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.BatteryMeterView;
+import com.android.systemui.FontSizeUtils;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.SignalClusterView;
+import com.android.systemui.statusbar.StatusBarIconView;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls everything regarding the icons in the status bar and on Keyguard, including, but not
+ * limited to: notification icons, signal cluster, additional status icons, and clock in the status
+ * bar.
+ */
+public class StatusBarIconController {
+
+    private Context mContext;
+    private PhoneStatusBar mPhoneStatusBar;
+    private Interpolator mLinearOutSlowIn;
+    private DemoStatusIcons mDemoStatusIcons;
+    private NotificationColorUtil mNotificationColorUtil;
+
+    private LinearLayout mSystemIconArea;
+    private LinearLayout mStatusIcons;
+    private SignalClusterView mSignalCluster;
+    private LinearLayout mStatusIconsKeyguard;
+    private IconMerger mNotificationIcons;
+    private View mNotificationIconArea;
+    private ImageView mMoreIcon;
+    private BatteryMeterView mBatteryMeterView;
+    private TextView mClock;
+
+    private int mIconSize;
+    private int mIconHPadding;
+
+    private int mIconTint = Color.WHITE;
+
+    public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
+            PhoneStatusBar phoneStatusBar) {
+        mContext = context;
+        mPhoneStatusBar = phoneStatusBar;
+        mNotificationColorUtil = NotificationColorUtil.getInstance(context);
+        mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
+        mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
+        mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
+        mNotificationIconArea = statusBar.findViewById(R.id.notification_icon_area_inner);
+        mNotificationIcons = (IconMerger) statusBar.findViewById(R.id.notificationIcons);
+        mMoreIcon = (ImageView) statusBar.findViewById(R.id.moreIcon);
+        mNotificationIcons.setOverflowIndicator(mMoreIcon);
+        mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
+        mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
+        mClock = (TextView) statusBar.findViewById(R.id.clock);
+        mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
+                android.R.interpolator.linear_out_slow_in);
+        updateResources();
+    }
+
+    public void updateResources() {
+        mIconSize = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_icon_size);
+        mIconHPadding = mContext.getResources().getDimensionPixelSize(
+                R.dimen.status_bar_icon_padding);
+        FontSizeUtils.updateFontSize(mClock, R.dimen.status_bar_clock_size);
+    }
+
+    public void addSystemIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
+        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
+        view.set(icon);
+        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
+        view = new StatusBarIconView(mContext, slot, null);
+        view.set(icon);
+        mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
+        applyIconTint();
+    }
+
+    public void updateSystemIcon(String slot, int index, int viewIndex,
+            StatusBarIcon old, StatusBarIcon icon) {
+        StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
+        view.set(icon);
+        view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
+        view.set(icon);
+        applyIconTint();
+    }
+
+    public void removeSystemIcon(String slot, int index, int viewIndex) {
+        mStatusIcons.removeViewAt(viewIndex);
+        mStatusIconsKeyguard.removeViewAt(viewIndex);
+    }
+
+    public void updateNotificationIcons(NotificationData notificationData) {
+        final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+                mIconSize + 2*mIconHPadding, mPhoneStatusBar.getStatusBarHeight());
+
+        ArrayList<NotificationData.Entry> activeNotifications =
+                notificationData.getActiveNotifications();
+        final int N = activeNotifications.size();
+        ArrayList<StatusBarIconView> toShow = new ArrayList<>(N);
+
+        // Filter out ambient notifications.
+        for (int i = 0; i < N; i++) {
+            NotificationData.Entry ent = activeNotifications.get(i);
+            if (notificationData.isAmbient(ent.key)
+                    && !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) {
+                continue;
+            }
+            toShow.add(ent.icon);
+        }
+
+        ArrayList<View> toRemove = new ArrayList<>();
+        for (int i=0; i<mNotificationIcons.getChildCount(); i++) {
+            View child = mNotificationIcons.getChildAt(i);
+            if (!toShow.contains(child)) {
+                toRemove.add(child);
+            }
+        }
+
+        final int toRemoveCount = toRemove.size();
+        for (int i = 0; i < toRemoveCount; i++) {
+            mNotificationIcons.removeView(toRemove.get(i));
+        }
+
+        for (int i=0; i<toShow.size(); i++) {
+            View v = toShow.get(i);
+            if (v.getParent() == null) {
+                mNotificationIcons.addView(v, i, params);
+            }
+        }
+
+        // Resort notification icons
+        final int childCount = mNotificationIcons.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View actual = mNotificationIcons.getChildAt(i);
+            StatusBarIconView expected = toShow.get(i);
+            if (actual == expected) {
+                continue;
+            }
+            mNotificationIcons.removeView(expected);
+            mNotificationIcons.addView(expected, i);
+        }
+
+        applyNotificationIconsTint();
+    }
+
+    public void hideSystemIconArea(boolean animate) {
+        animateHide(mSystemIconArea, animate);
+    }
+
+    public void showSystemIconArea(boolean animate) {
+        animateShow(mSystemIconArea, animate);
+    }
+
+    public void hideNotificationIconArea(boolean animate) {
+        animateHide(mNotificationIconArea, animate);
+    }
+
+    public void showNotificationIconArea(boolean animate) {
+        animateShow(mNotificationIconArea, animate);
+    }
+
+    public void setClockVisibility(boolean visible) {
+        mClock.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    public void dump(PrintWriter pw) {
+        int N = mStatusIcons.getChildCount();
+        pw.println("  system icons: " + N);
+        for (int i=0; i<N; i++) {
+            StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
+            pw.println("    [" + i + "] icon=" + ic);
+        }
+    }
+
+    public void dispatchDemoCommand(String command, Bundle args) {
+        if (mDemoStatusIcons == null) {
+            mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize);
+        }
+        mDemoStatusIcons.dispatchDemoCommand(command, args);
+    }
+
+    /**
+     * Hides a view.
+     */
+    private void animateHide(final View v, boolean animate) {
+        v.animate().cancel();
+        if (!animate) {
+            v.setAlpha(0f);
+            v.setVisibility(View.INVISIBLE);
+            return;
+        }
+        v.animate()
+                .alpha(0f)
+                .setDuration(160)
+                .setStartDelay(0)
+                .setInterpolator(PhoneStatusBar.ALPHA_OUT)
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        v.setVisibility(View.INVISIBLE);
+                    }
+                });
+    }
+
+    /**
+     * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
+     */
+    private void animateShow(View v, boolean animate) {
+        v.animate().cancel();
+        v.setVisibility(View.VISIBLE);
+        if (!animate) {
+            v.setAlpha(1f);
+            return;
+        }
+        v.animate()
+                .alpha(1f)
+                .setDuration(320)
+                .setInterpolator(PhoneStatusBar.ALPHA_IN)
+                .setStartDelay(50)
+
+                // We need to clean up any pending end action from animateHide if we call
+                // both hide and show in the same frame before the animation actually gets started.
+                // cancel() doesn't really remove the end action.
+                .withEndAction(null);
+
+        // Synchronize the motion with the Keyguard fading if necessary.
+        if (mPhoneStatusBar.isKeyguardFadingAway()) {
+            v.animate()
+                    .setDuration(mPhoneStatusBar.getKeyguardFadingAwayDuration())
+                    .setInterpolator(mLinearOutSlowIn)
+                    .setStartDelay(mPhoneStatusBar.getKeyguardFadingAwayDelay())
+                    .start();
+        }
+    }
+
+    public void setIconTint(int tint) {
+        mIconTint = tint;
+        applyIconTint();
+    }
+
+    private void applyIconTint() {
+        for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
+            StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
+            v.setImageTintList(ColorStateList.valueOf(mIconTint));
+        }
+        mSignalCluster.setIconTint(mIconTint);
+        mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
+        mBatteryMeterView.setIconTint(mIconTint);
+        mClock.setTextColor(mIconTint);
+        applyNotificationIconsTint();
+    }
+
+    private void applyNotificationIconsTint() {
+        for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
+            StatusBarIconView v = (StatusBarIconView) mNotificationIcons.getChildAt(i);
+            boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
+            boolean colorize = !isPreL || isGrayscale(v);
+            if (colorize) {
+                v.setImageTintMode(PorterDuff.Mode.SRC_ATOP);
+                v.setImageTintList(ColorStateList.valueOf(mIconTint));
+            }
+        }
+    }
+
+    private boolean isGrayscale(StatusBarIconView v) {
+        Object isGrayscale = v.getTag(R.id.icon_is_grayscale);
+        if (isGrayscale != null) {
+            return Boolean.TRUE.equals(isGrayscale);
+        }
+        boolean grayscale = mNotificationColorUtil.isGrayscaleIcon(v.getDrawable());
+        v.setTag(R.id.icon_is_grayscale, grayscale);
+        return grayscale;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
index ad4c211..18983ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
@@ -17,35 +17,25 @@
 package com.android.systemui.statusbar.policy;
 
 import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.ActionListener;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTracker.WifiListener;
 import com.android.systemui.R;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 
-
-// TODO: Unify this logic with platform settings (see WifiSettings and AccessPoint). There is a
-// fair amount of complexity here in statuses and logic beyond just connected/disconnected.
-public class AccessPointControllerImpl implements NetworkController.AccessPointController {
+public class AccessPointControllerImpl
+        implements NetworkController.AccessPointController, WifiListener {
     private static final String TAG = "AccessPointController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -63,25 +53,18 @@
 
     private final Context mContext;
     private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
-    private final WifiManager mWifiManager;
+    private final WifiTracker mWifiTracker;
     private final UserManager mUserManager;
-    private final Receiver mReceiver = new Receiver();
 
-    private NetworkControllerImpl mNetworkController;
-    private boolean mScanning;
     private int mCurrentUser;
 
     public AccessPointControllerImpl(Context context) {
         mContext = context;
-        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mWifiTracker = new WifiTracker(context, this, false, true);
         mCurrentUser = ActivityManager.getCurrentUser();
     }
 
-    void setNetworkController(NetworkControllerImpl networkController) {
-        mNetworkController = networkController;
-    }
-
     public boolean canConfigWifi() {
         return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI,
                 new UserHandle(mCurrentUser));
@@ -96,7 +79,9 @@
         if (callback == null || mCallbacks.contains(callback)) return;
         if (DEBUG) Log.d(TAG, "addCallback " + callback);
         mCallbacks.add(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        if (mCallbacks.size() == 1) {
+            mWifiTracker.startTracking();
+        }
     }
 
     @Override
@@ -104,37 +89,40 @@
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         mCallbacks.remove(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        if (mCallbacks.isEmpty()) {
+            mWifiTracker.stopTracking();
+        }
     }
 
     @Override
     public void scanForAccessPoints() {
-        if (mScanning) return;
         if (DEBUG) Log.d(TAG, "scan!");
-        mScanning = mWifiManager.startScan();
-        // Grab current networks immediately while we wait for scan.
-        updateAccessPoints();
+        mWifiTracker.forceScan();
+    }
+
+    @Override
+    public int getIcon(AccessPoint ap) {
+        int level = ap.getLevel();
+        return ICONS[level >= 0 ? level : 0];
     }
 
     public boolean connect(AccessPoint ap) {
         if (ap == null) return false;
-        if (DEBUG) Log.d(TAG, "connect networkId=" + ap.networkId);
-        if (ap.networkId < 0) {
+        if (DEBUG) Log.d(TAG, "connect networkId=" + ap.getConfig().networkId);
+        if (ap.isSaved()) {
+            mWifiTracker.getManager().connect(ap.getConfig().networkId, mConnectListener);
+        } else {
             // Unknown network, need to add it.
-            if (ap.hasSecurity) {
+            if (ap.getSecurity() != AccessPoint.SECURITY_NONE) {
                 Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
-                intent.putExtra(EXTRA_START_CONNECT_SSID, ap.ssid);
+                intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsid());
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 fireSettingsIntentCallback(intent);
                 return true;
             } else {
-                WifiConfiguration config = new WifiConfiguration();
-                config.SSID = "\"" + ap.ssid + "\"";
-                config.allowedKeyManagement.set(KeyMgmt.NONE);
-                mWifiManager.connect(config, mConnectListener);
+                ap.generateOpenNetworkConfig();
+                mWifiTracker.getManager().connect(ap.getConfig(), mConnectListener);
             }
-        } else {
-            mWifiManager.connect(ap.networkId, mConnectListener);
         }
         return false;
     }
@@ -145,76 +133,28 @@
         }
     }
 
-    private void fireAcccessPointsCallback(AccessPoint[] aps) {
+    private void fireAcccessPointsCallback(List<AccessPoint> aps) {
         for (AccessPointCallback callback : mCallbacks) {
             callback.onAccessPointsChanged(aps);
         }
     }
 
-    private static String trimDoubleQuotes(String v) {
-        return v != null && v.length() >= 2 && v.charAt(0) == '\"'
-                && v.charAt(v.length() - 1) == '\"' ? v.substring(1, v.length() - 1) : v;
+    public void dump(PrintWriter pw) {
+        mWifiTracker.dump(pw);
     }
 
-    private int getConnectedNetworkId(WifiInfo wifiInfo) {
-        return wifiInfo != null ? wifiInfo.getNetworkId() : AccessPoint.NO_NETWORK;
+    @Override
+    public void onWifiStateChanged(int state) {
     }
 
-    private ArrayMap<String, WifiConfiguration> getConfiguredNetworksBySsid() {
-        final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
-        if (configs == null || configs.size() == 0) return ArrayMap.EMPTY;
-        final ArrayMap<String, WifiConfiguration> rt = new ArrayMap<String, WifiConfiguration>();
-        for (WifiConfiguration config : configs) {
-            rt.put(trimDoubleQuotes(config.SSID), config);
-        }
-        return rt;
+    @Override
+    public void onConnectedChanged() {
+        fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
     }
 
-    private void updateAccessPoints() {
-        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-        final int connectedNetworkId = getConnectedNetworkId(wifiInfo);
-        if (DEBUG) Log.d(TAG, "connectedNetworkId: " + connectedNetworkId);
-        final List<ScanResult> scanResults = mWifiManager.getScanResults();
-        final ArrayMap<String, WifiConfiguration> configured = getConfiguredNetworksBySsid();
-        if (DEBUG) Log.d(TAG, "scanResults: " + scanResults);
-        final List<AccessPoint> aps = new ArrayList<AccessPoint>(scanResults.size());
-        final ArraySet<String> ssids = new ArraySet<String>();
-        for (ScanResult scanResult : scanResults) {
-            if (scanResult == null) {
-                continue;
-            }
-            final String ssid = scanResult.SSID;
-            if (TextUtils.isEmpty(ssid) || ssids.contains(ssid)) continue;
-            ssids.add(ssid);
-            final WifiConfiguration config = configured.get(ssid);
-            final int level = WifiManager.calculateSignalLevel(scanResult.level, ICONS.length);
-            final AccessPoint ap = new AccessPoint();
-            ap.isConfigured = config != null;
-            ap.networkId = config != null ? config.networkId : AccessPoint.NO_NETWORK;
-            ap.ssid = ssid;
-            // Connected if either:
-            // -The network ID in the active WifiInfo matches this network's ID.
-            // -The network is ephemeral (no configuration) but the SSID matches.
-            ap.isConnected = (ap.networkId != AccessPoint.NO_NETWORK
-                    && ap.networkId == connectedNetworkId) ||
-                    (ap.networkId == WifiConfiguration.INVALID_NETWORK_ID && wifiInfo != null &&
-                    ap.ssid.equals(trimDoubleQuotes(wifiInfo.getSSID())));
-            if (ap.isConnected && mNetworkController != null) {
-                // Ensure we have the connected network's RSSI.
-                ap.level = mNetworkController.getConnectedWifiLevel();
-            } else {
-                ap.level = level;
-            }
-            ap.iconId = ICONS[ap.level];
-            // Based on Settings AccessPoint#getSecurity, keep up to date
-            // with better methods of determining no security or not.
-            ap.hasSecurity = scanResult.capabilities.contains("WEP")
-                    || scanResult.capabilities.contains("PSK")
-                    || scanResult.capabilities.contains("EAP");
-            aps.add(ap);
-        }
-        Collections.sort(aps, mByStrength);
-        fireAcccessPointsCallback(aps.toArray(new AccessPoint[aps.size()]));
+    @Override
+    public void onAccessPointsChanged() {
+        fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
     }
 
     private final ActionListener mConnectListener = new ActionListener() {
@@ -228,49 +168,4 @@
             if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
         }
     };
-
-    private final Comparator<AccessPoint> mByStrength = new Comparator<AccessPoint> () {
-        @Override
-        public int compare(AccessPoint lhs, AccessPoint rhs) {
-            return -Integer.compare(score(lhs), score(rhs));
-        }
-
-        private int score(AccessPoint ap) {
-            return ap.level + (ap.isConnected ? 20 : 0) + (ap.isConfigured ? 10 : 0);
-        }
-    };
-
-    private final class Receiver extends BroadcastReceiver {
-        private boolean mRegistered;
-
-        public void setListening(boolean listening) {
-            if (listening && !mRegistered) {
-                if (DEBUG) Log.d(TAG, "Registering receiver");
-                final IntentFilter filter = new IntentFilter();
-                filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-                filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
-                filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
-                filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
-                filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
-                filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
-                filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-                filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
-                mContext.registerReceiver(this, filter);
-                mRegistered = true;
-            } else if (!listening && mRegistered) {
-                if (DEBUG) Log.d(TAG, "Unregistering receiver");
-                mContext.unregisterReceiver(this);
-                mRegistered = false;
-            }
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
-            if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
-                updateAccessPoints();
-                mScanning = false;
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 2e3e67a..2e96dd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -44,6 +44,8 @@
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.Callback, ExpandHelper.Callback,
@@ -442,6 +444,27 @@
         mUser = user;
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("HeadsUpNotificationView state:");
+        pw.print("  mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay);
+        pw.print("  mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
+        pw.print("  mMostRecentPackageName="); pw.println(mMostRecentPackageName);
+        pw.print("  mStartTouchTime="); pw.println(mStartTouchTime);
+        pw.print("  now="); pw.println(SystemClock.elapsedRealtime());
+        pw.print("  mUser="); pw.println(mUser);
+        if (mHeadsUp == null) {
+            pw.println("  mHeadsUp=null");
+        } else {
+            pw.print("  mHeadsUp="); pw.println(mHeadsUp.notification.getKey());
+        }
+        int N = mSnoozedPackages.size();
+        pw.println("  snoozed packages: " + N);
+        for (int i = 0; i < N; i++) {
+            pw.print("    "); pw.print(mSnoozedPackages.valueAt(i));
+            pw.print(", "); pw.println(mSnoozedPackages.keyAt(i));
+        }
+    }
+
     private class EdgeSwipeHelper implements Gefingerpoken {
         private static final boolean DEBUG_EDGE_SWIPE = false;
         private final float mTouchSlop;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index e8023bb..ba938cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -28,7 +28,6 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.systemui.R;
@@ -97,50 +96,6 @@
         updateTelephony();
     }
 
-    /**
-     * Get (the mobile parts of) the carrier string.
-     *
-     * @param currentLabel can be used for concatenation, currently just empty
-     * @param connected whether the device has connection to the internet at all
-     * @param isMobileLabel whether to always return the network or just when data is connected
-     */
-    public String getLabel(String currentLabel, boolean connected, boolean isMobileLabel) {
-        if (!mCurrentState.enabled) {
-            return "";
-        } else {
-            String mobileLabel = "";
-            // We want to show the carrier name if in service and either:
-            // - We are connected to mobile data, or
-            // - We are not connected to mobile data, as long as the *reason* packets are not
-            //   being routed over that link is that we have better connectivity via wifi.
-            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
-            // is connected, we show nothing.
-            // Otherwise (nothing connected) we show "No internet connection".
-            if (mCurrentState.dataConnected) {
-                mobileLabel = mCurrentState.networkName;
-            } else if (connected || mCurrentState.isEmergency) {
-                if (mCurrentState.connected || mCurrentState.isEmergency) {
-                    // The isEmergencyOnly test covers the case of a phone with no SIM
-                    mobileLabel = mCurrentState.networkName;
-                }
-            } else {
-                mobileLabel = mContext.getString(
-                        R.string.status_bar_settings_signal_meter_disconnected);
-            }
-
-            if (currentLabel.length() != 0) {
-                currentLabel = currentLabel + mNetworkNameSeparator;
-            }
-            // Now for things that should only be shown when actually using mobile data.
-            if (isMobileLabel) {
-                return currentLabel + mobileLabel;
-            } else {
-                return currentLabel
-                        + (mCurrentState.dataConnected ? mobileLabel : currentLabel);
-            }
-        }
-    }
-
     public int getDataContentDescription() {
         return getIcons().mDataContentDescription;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 3cffc85..9212837 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -18,6 +18,10 @@
 
 import android.content.Intent;
 
+import com.android.settingslib.wifi.AccessPoint;
+
+import java.util.List;
+
 public interface NetworkController {
 
     boolean hasMobileDataFeature();
@@ -50,25 +54,14 @@
         void addAccessPointCallback(AccessPointCallback callback);
         void removeAccessPointCallback(AccessPointCallback callback);
         void scanForAccessPoints();
+        int getIcon(AccessPoint ap);
         boolean connect(AccessPoint ap);
         boolean canConfigWifi();
 
         public interface AccessPointCallback {
-            void onAccessPointsChanged(AccessPoint[] accessPoints);
+            void onAccessPointsChanged(List<AccessPoint> accessPoints);
             void onSettingsActivityTriggered(Intent settingsIntent);
         }
-
-        public static class AccessPoint {
-            public static final int NO_NETWORK = -1;  // see WifiManager
-
-            public int networkId;
-            public int iconId;
-            public String ssid;
-            public boolean isConnected;
-            public boolean isConfigured;
-            public boolean hasSecurity;
-            public int level;  // 0 - 5
-        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 1d37ee3..bb3eb7ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -17,8 +17,6 @@
 package com.android.systemui.statusbar.policy;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
-import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
-import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -84,12 +82,6 @@
     private final AccessPointControllerImpl mAccessPoints;
     private final MobileDataControllerImpl mMobileDataController;
 
-    // Network types that replace the carrier label if the device does not support mobile data.
-    private boolean mBluetoothTethered = false;
-    private boolean mEthernetConnected = false;
-
-    // state of inet connection
-    private boolean mConnected = false;
     private boolean mInetCondition; // Used for Logging and demo.
 
     // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
@@ -107,8 +99,6 @@
 
     // All the callbacks.
     private ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<EmergencyListener>();
-    private ArrayList<CarrierLabelListener> mCarrierListeners =
-            new ArrayList<CarrierLabelListener>();
     private ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
     private ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
             new ArrayList<NetworkSignalChangedCallback>();
@@ -166,7 +156,6 @@
 
         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
         updateAirplaneMode(true /* force callback */);
-        mAccessPoints.setNetworkController(this);
     }
 
     private void registerListeners() {
@@ -222,11 +211,6 @@
         listener.setEmergencyCallsOnly(isEmergencyOnly());
     }
 
-    public void addCarrierLabel(CarrierLabelListener listener) {
-        mCarrierListeners.add(listener);
-        refreshCarrierLabel();
-    }
-
     private void notifyMobileDataEnabled(boolean enabled) {
         final int length = mSignalsChangedCallbacks.size();
         for (int i = 0; i < length; i++) {
@@ -288,9 +272,6 @@
         for (int i = 0; i < length; i++) {
             mEmergencyListeners.get(i).setEmergencyCallsOnly(emergencyOnly);
         }
-        // If the emergency has a chance to change, then so does the carrier
-        // label.
-        refreshCarrierLabel();
     }
 
     public void addSignalCluster(SignalCluster cluster) {
@@ -342,7 +323,6 @@
         mCurrentUserId = newUserId;
         mAccessPoints.onUserSwitched(newUserId);
         updateConnectivity();
-        refreshCarrierLabel();
     }
 
     @Override
@@ -354,14 +334,12 @@
         if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
                 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
             updateConnectivity();
-            refreshCarrierLabel();
         } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
             mConfig = Config.readConfig(mContext);
             handleConfigurationChanged();
         } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
             refreshLocale();
             updateAirplaneMode(false);
-            refreshCarrierLabel();
         } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)) {
             // We are using different subs now, we might be able to make calls.
             recalculateEmergency();
@@ -397,7 +375,6 @@
             mobileSignalController.setConfiguration(mConfig);
         }
         refreshLocale();
-        refreshCarrierLabel();
     }
 
     private void updateMobileControllers() {
@@ -503,7 +480,6 @@
                 mobileSignalController.setAirplaneMode(mAirplaneMode);
             }
             notifyListeners();
-            refreshCarrierLabel();
         }
     }
 
@@ -567,10 +543,7 @@
             Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
         }
 
-        mConnected = !mConnectedTransports.isEmpty();
         mInetCondition = !mValidatedTransports.isEmpty();
-        mBluetoothTethered = mConnectedTransports.get(TRANSPORT_BLUETOOTH);
-        mEthernetConnected = mConnectedTransports.get(TRANSPORT_ETHERNET);
 
         pushConnectivityToSignals();
     }
@@ -589,59 +562,6 @@
                 mValidatedTransports.get(mWifiSignalController.getTransportType()) ? 1 : 0);
     }
 
-    /**
-     * Recalculate and update the carrier label.
-     */
-    void refreshCarrierLabel() {
-        Context context = mContext;
-
-        WifiSignalController.WifiState wifiState = mWifiSignalController.getState();
-        String label = "";
-        for (MobileSignalController controller : mMobileSignalControllers.values()) {
-            label = controller.getLabel(label, mConnected, mHasMobileDataFeature);
-        }
-
-        // TODO Simplify this ugliness, some of the flows below shouldn't be possible anymore
-        // but stay for the sake of history.
-        if (mBluetoothTethered && !mHasMobileDataFeature) {
-            label = mContext.getString(R.string.bluetooth_tethered);
-        }
-
-        if (mEthernetConnected && !mHasMobileDataFeature) {
-            label = context.getString(R.string.ethernet_label);
-        }
-
-        if (mAirplaneMode && !isEmergencyOnly()) {
-            // combined values from connected wifi take precedence over airplane mode
-            if (wifiState.connected && mHasMobileDataFeature) {
-                // Suppress "No internet connection." from mobile if wifi connected.
-                label = "";
-            } else {
-                 if (!mHasMobileDataFeature) {
-                      label = context.getString(
-                              R.string.status_bar_settings_signal_meter_disconnected);
-                 }
-            }
-        } else if (!isMobileDataConnected() && !wifiState.connected && !mBluetoothTethered &&
-                 !mEthernetConnected && !mHasMobileDataFeature) {
-            // Pretty much no connection.
-            label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
-        }
-
-        // for mobile devices, we always show mobile connection info here (SPN/PLMN)
-        // for other devices, we show whatever network is connected
-        // This is determined above by references to mHasMobileDataFeature.
-        int length = mCarrierListeners.size();
-        for (int i = 0; i < length; i++) {
-            mCarrierListeners.get(i).setCarrierLabel(label);
-        }
-    }
-
-    private boolean isMobileDataConnected() {
-        MobileSignalController controller = getDataController();
-        return controller != null ? controller.getState().dataConnected : false;
-    }
-
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NetworkController state:");
 
@@ -649,10 +569,6 @@
         pw.print("  hasVoiceCallingFeature()=");
         pw.println(hasVoiceCallingFeature());
 
-        pw.println("  - Bluetooth ----");
-        pw.print("  mBtReverseTethered=");
-        pw.println(mBluetoothTethered);
-
         pw.println("  - connectivity ------");
         pw.print("  mConnectedTransports=");
         pw.println(mConnectedTransports);
@@ -669,6 +585,8 @@
             mobileSignalController.dump(pw);
         }
         mWifiSignalController.dump(pw);
+
+        mAccessPoints.dump(pw);
     }
 
     private boolean mDemoMode;
@@ -695,7 +613,6 @@
             mWifiSignalController.resetLastState();
             registerListeners();
             notifyAllListeners();
-            refreshCarrierLabel();
         } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
             String airplane = args.getString("airplane");
             if (airplane != null) {
@@ -787,7 +704,6 @@
                 controller.getState().enabled = show;
                 controller.notifyListeners();
             }
-            refreshCarrierLabel();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 14c3d9c..8379b93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -167,7 +167,6 @@
         if (isDirty()) {
             saveLastState();
             notifyListeners();
-            mNetworkController.refreshCarrierLabel();
         }
     }
 
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 5a90324..6a7201c 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -36,4 +36,6 @@
 # UI it doesn't own. This is necessary to allow screenshots to be taken
 LOCAL_CERTIFICATE := platform
 
+include frameworks/base/packages/SettingsLib/common.mk
+
 include $(BUILD_PACKAGE)
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 1aa7366..6771988 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3479,6 +3479,10 @@
         if (!mForcedNavigationBarColor) {
             mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
         }
+        if (a.getBoolean(R.styleable.Window_windowHasLightStatusBar, false)) {
+            decor.setSystemUiVisibility(
+                    decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+        }
 
         if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion
                 >= android.os.Build.VERSION_CODES.HONEYCOMB) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index d4032cc..8320656 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -43,6 +43,7 @@
 import android.graphics.Rect;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
+import android.media.AudioService;
 import android.media.IAudioService;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -376,6 +377,8 @@
     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mHasSoftInput = false;
     boolean mTranslucentDecorEnabled = true;
+    boolean mUseTvRouting;
+    boolean mUseMasterVolume;
 
     int mPointerLocationMode = 0; // guarded by mLock
 
@@ -1262,6 +1265,10 @@
         mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_triplePressOnPowerBehavior);
 
+        mUseTvRouting = AudioService.getPlatformType(mContext) == AudioService.PLATFORM_TELEVISION;
+        mUseMasterVolume = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useMasterVolume);
+
         readConfigurationDependentBehaviors();
 
         mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -4534,6 +4541,10 @@
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
+                if (mUseTvRouting) {
+                    // On TVs volume keys never go to the foreground app
+                    result &= ~ACTION_PASS_TO_USER;
+                }
                 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                     if (down) {
                         if (interactive && !mScreenshotChordVolumeDownKeyTriggered
@@ -4595,11 +4606,15 @@
                     }
 
                     if ((result & ACTION_PASS_TO_USER) == 0) {
-                        // If we aren't passing to the user and no one else
-                        // handled it send it to the session manager to figure
-                        // out.
-                        MediaSessionLegacyHelper.getHelper(mContext)
-                                .sendVolumeKeyEvent(event, true);
+                        if (mUseTvRouting) {
+                            dispatchDirectAudioEvent(event);
+                        } else {
+                            // If we aren't passing to the user and no one else
+                            // handled it send it to the session manager to
+                            // figure out.
+                            MediaSessionLegacyHelper.getHelper(mContext)
+                                    .sendVolumeKeyEvent(event, true);
+                        }
                         break;
                     }
                 }
@@ -4732,6 +4747,7 @@
                     msg.setAsynchronous(true);
                     msg.sendToTarget();
                 }
+                break;
             }
         }
 
@@ -4844,6 +4860,59 @@
         return false;
     }
 
+    private void dispatchDirectAudioEvent(KeyEvent event) {
+        if (event.getAction() != KeyEvent.ACTION_DOWN) {
+            return;
+        }
+        int keyCode = event.getKeyCode();
+        int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND;
+        String pkgName = mContext.getOpPackageName();
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_VOLUME_UP:
+                try {
+                    if (mUseMasterVolume) {
+                        getAudioService().adjustMasterVolume(AudioManager.ADJUST_RAISE, flags,
+                                pkgName);
+                    } else {
+                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
+                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
+                }
+                break;
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+                try {
+                    if (mUseMasterVolume) {
+                        getAudioService().adjustMasterVolume(AudioManager.ADJUST_LOWER, flags,
+                                pkgName);
+                    } else {
+                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
+                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
+                }
+                break;
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+                try {
+                    if (event.getRepeatCount() == 0) {
+                        if (mUseMasterVolume) {
+                            getAudioService().adjustMasterVolume(AudioManager.ADJUST_TOGGLE_MUTE,
+                                    flags, pkgName);
+                        } else {
+                            getAudioService().adjustSuggestedStreamVolume(
+                                    AudioManager.ADJUST_TOGGLE_MUTE,
+                                    AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
+                        }
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
+                }
+                break;
+        }
+    }
+
     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
         if (DEBUG_INPUT) {
             Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 4e89566..e979a1be 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -1882,4 +1882,15 @@
         }
     }
 
+    /**
+     * For USAGE_IO_OUTPUT, destroy() implies setSurface(null).
+     *
+     */
+    @Override
+    public void destroy() {
+        if((mUsage & USAGE_IO_OUTPUT) != 0) {
+            setSurface(null);
+        }
+        super.destroy();
+    }
 }
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 20b07e7..0f967fc 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -241,8 +241,7 @@
                 addI64(0);
                 addI64(0);
                 addI64(0);
-            }
-            else {
+            } else {
                 addI32((int)obj.getID(null));
             }
         } else {
@@ -619,6 +618,289 @@
         return mPos;
     }
 
+    private static void addToPack(FieldPacker fp, Object obj) {
+        if (obj instanceof Boolean) {
+            fp.addBoolean(((Boolean)obj).booleanValue());
+            return;
+        }
+
+        if (obj instanceof Byte) {
+            fp.addI8(((Byte)obj).byteValue());
+            return;
+        }
+
+        if (obj instanceof Short) {
+            fp.addI16(((Short)obj).shortValue());
+            return;
+        }
+
+        if (obj instanceof Integer) {
+            fp.addI32(((Integer)obj).intValue());
+            return;
+        }
+
+        if (obj instanceof Long) {
+            fp.addI64(((Long)obj).longValue());
+            return;
+        }
+
+        if (obj instanceof Float) {
+            fp.addF32(((Float)obj).floatValue());
+            return;
+        }
+
+        if (obj instanceof Double) {
+            fp.addF64(((Double)obj).doubleValue());
+            return;
+        }
+
+        if (obj instanceof Byte2) {
+            fp.addI8((Byte2)obj);
+            return;
+        }
+
+        if (obj instanceof Byte3) {
+            fp.addI8((Byte3)obj);
+            return;
+        }
+
+        if (obj instanceof Byte4) {
+            fp.addI8((Byte4)obj);
+            return;
+        }
+
+        if (obj instanceof Short2) {
+            fp.addI16((Short2)obj);
+            return;
+        }
+
+        if (obj instanceof Short3) {
+            fp.addI16((Short3)obj);
+            return;
+        }
+
+        if (obj instanceof Short4) {
+            fp.addI16((Short4)obj);
+            return;
+        }
+
+        if (obj instanceof Int2) {
+            fp.addI32((Int2)obj);
+            return;
+        }
+
+        if (obj instanceof Int3) {
+            fp.addI32((Int3)obj);
+            return;
+        }
+
+        if (obj instanceof Int4) {
+            fp.addI32((Int4)obj);
+            return;
+        }
+
+        if (obj instanceof Long2) {
+            fp.addI64((Long2)obj);
+            return;
+        }
+
+        if (obj instanceof Long3) {
+            fp.addI64((Long3)obj);
+            return;
+        }
+
+        if (obj instanceof Long4) {
+            fp.addI64((Long4)obj);
+            return;
+        }
+
+        if (obj instanceof Float2) {
+            fp.addF32((Float2)obj);
+            return;
+        }
+
+        if (obj instanceof Float3) {
+            fp.addF32((Float3)obj);
+            return;
+        }
+
+        if (obj instanceof Float4) {
+            fp.addF32((Float4)obj);
+            return;
+        }
+
+        if (obj instanceof Double2) {
+            fp.addF64((Double2)obj);
+            return;
+        }
+
+        if (obj instanceof Double3) {
+            fp.addF64((Double3)obj);
+            return;
+        }
+
+        if (obj instanceof Double4) {
+            fp.addF64((Double4)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix2f) {
+            fp.addMatrix((Matrix2f)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix3f) {
+            fp.addMatrix((Matrix3f)obj);
+            return;
+        }
+
+        if (obj instanceof Matrix4f) {
+            fp.addMatrix((Matrix4f)obj);
+            return;
+        }
+
+        if (obj instanceof BaseObj) {
+            fp.addObj((BaseObj)obj);
+            return;
+        }
+    }
+
+    private static int getPackedSize(Object obj) {
+        if (obj instanceof Boolean) {
+            return 1;
+        }
+
+        if (obj instanceof Byte) {
+            return 1;
+        }
+
+        if (obj instanceof Short) {
+            return 2;
+        }
+
+        if (obj instanceof Integer) {
+            return 4;
+        }
+
+        if (obj instanceof Long) {
+            return 8;
+        }
+
+        if (obj instanceof Float) {
+            return 4;
+        }
+
+        if (obj instanceof Double) {
+            return 8;
+        }
+
+        if (obj instanceof Byte2) {
+            return 2;
+        }
+
+        if (obj instanceof Byte3) {
+            return 3;
+        }
+
+        if (obj instanceof Byte4) {
+            return 4;
+        }
+
+        if (obj instanceof Short2) {
+            return 4;
+        }
+
+        if (obj instanceof Short3) {
+            return 6;
+        }
+
+        if (obj instanceof Short4) {
+            return 8;
+        }
+
+        if (obj instanceof Int2) {
+            return 8;
+        }
+
+        if (obj instanceof Int3) {
+            return 12;
+        }
+
+        if (obj instanceof Int4) {
+            return 16;
+        }
+
+        if (obj instanceof Long2) {
+            return 16;
+        }
+
+        if (obj instanceof Long3) {
+            return 24;
+        }
+
+        if (obj instanceof Long4) {
+            return 32;
+        }
+
+        if (obj instanceof Float2) {
+            return 8;
+        }
+
+        if (obj instanceof Float3) {
+            return 12;
+        }
+
+        if (obj instanceof Float4) {
+            return 16;
+        }
+
+        if (obj instanceof Double2) {
+            return 16;
+        }
+
+        if (obj instanceof Double3) {
+            return 24;
+        }
+
+        if (obj instanceof Double4) {
+            return 32;
+        }
+
+        if (obj instanceof Matrix2f) {
+            return 16;
+        }
+
+        if (obj instanceof Matrix3f) {
+            return 36;
+        }
+
+        if (obj instanceof Matrix4f) {
+            return 64;
+        }
+
+        if (obj instanceof BaseObj) {
+            if (RenderScript.sPointerSize == 8) {
+                return 32;
+            } else {
+                return 4;
+            }
+        }
+
+        return 0;
+    }
+
+    static FieldPacker createFieldPack(Object[] args) {
+        int len = 0;
+        for (Object arg : args) {
+            len += getPackedSize(arg);
+        }
+        FieldPacker fp = new FieldPacker(len);
+        for (Object arg : args) {
+            addToPack(fp, arg);
+        }
+        return fp;
+    }
+
     private final byte mData[];
     private int mPos;
     private int mLen;
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 271fe05..94aa857 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -313,6 +313,15 @@
           sizes, depClosures, depFieldIDs);
     }
 
+    native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
+        long[] fieldIDs, long[] values, int[] sizes);
+    synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
+        long[] fieldIDs, long[] values, int[] sizes) {
+      validate();
+      return rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
+          values, sizes);
+    }
+
     native void rsnClosureSetArg(long con, long closureID, int index,
       long value, int size);
     synchronized void nClosureSetArg(long closureID, int index, long value,
@@ -330,10 +339,10 @@
       rsnClosureSetGlobal(mContext, closureID, fieldID, value, size);
     }
 
-    native long rsnScriptGroup2Create(long con, long[] closures);
-    synchronized long nScriptGroup2Create(long[] closures) {
+    native long rsnScriptGroup2Create(long con, String cachePath, long[] closures);
+    synchronized long nScriptGroup2Create(String cachePath, long[] closures) {
       validate();
-      return rsnScriptGroup2Create(mContext, closures);
+      return rsnScriptGroup2Create(mContext, cachePath, closures);
     }
 
     native void rsnScriptGroup2Execute(long con, long groupID);
@@ -745,6 +754,12 @@
         return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
     }
 
+    native long  rsnScriptInvokeIDCreate(long con, long sid, int slot);
+    synchronized long nScriptInvokeIDCreate(long sid, int slot) {
+        validate();
+        return rsnScriptInvokeIDCreate(mContext, sid, slot);
+    }
+
     native long  rsnScriptFieldIDCreate(long con, long sid, int slot);
     synchronized long nScriptFieldIDCreate(long sid, int slot) {
         validate();
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index eb1687a..d352130 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -66,6 +66,46 @@
     }
 
     /**
+     * @hide Pending API review
+     * InvokeID is an identifier for an invoke function. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getInvokeID_funcname()".
+     *
+     */
+    public static final class InvokeID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        InvokeID(long id, RenderScript rs, Script s, int slot) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+        }
+    }
+
+    private final SparseArray<InvokeID> mIIDs = new SparseArray<InvokeID>();
+    /**
+     * @hide Pending API review
+     * Only to be used by generated reflected classes.
+     */
+    protected InvokeID createInvokeID(int slot) {
+        InvokeID i = mIIDs.get(slot);
+        if (i != null) {
+            return i;
+        }
+
+        long id = mRS.nScriptInvokeIDCreate(getID(mRS), slot);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create KernelID");
+        }
+
+        i = new InvokeID(id, mRS, this, slot);
+        mIIDs.put(slot, i);
+        return i;
+    }
+
+    /**
      * FieldID is an identifier for a Script + exported field pair. It is used
      * as an identifier for ScriptGroup creation.
      *
diff --git a/rs/java/android/renderscript/ScriptGroup2.java b/rs/java/android/renderscript/ScriptGroup2.java
index dcad787..113b896 100644
--- a/rs/java/android/renderscript/ScriptGroup2.java
+++ b/rs/java/android/renderscript/ScriptGroup2.java
@@ -8,9 +8,6 @@
 import java.util.Map;
 
 /**
-   @hide Pending Android public API approval.
- */
-/**
 
 ******************************
 You have tried to change the API from what has been previously approved.
@@ -37,6 +34,8 @@
     private Future mReturnFuture;
     private Map<Script.FieldID, Future> mGlobalFuture;
 
+    private FieldPacker mFP;
+
     private static final String TAG = "Closure";
 
     public Closure(long id, RenderScript rs) {
@@ -92,6 +91,44 @@
       setID(id);
     }
 
+    public Closure(RenderScript rs, Script.InvokeID invokeID,
+        Object[] args, Map<Script.FieldID, Object> globals) {
+      super(0, rs);
+      mFP = FieldPacker.createFieldPack(args);
+
+      mBindings = new HashMap<Script.FieldID, Object>();
+      mGlobalFuture = new HashMap<Script.FieldID, Future>();
+
+      int numValues = globals.size();
+
+      long[] fieldIDs = new long[numValues];
+      long[] values = new long[numValues];
+      int[] sizes = new int[numValues];
+      long[] depClosures = new long[numValues];
+      long[] depFieldIDs = new long[numValues];
+
+      int i = 0;
+      for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
+        Object obj = entry.getValue();
+        Script.FieldID fieldID = entry.getKey();
+        fieldIDs[i] = fieldID.getID(rs);
+        if (obj instanceof UnboundValue) {
+          UnboundValue unbound = (UnboundValue)obj;
+          unbound.addReference(this, fieldID);
+        } else {
+          // TODO(yangni): Verify obj not a future.
+          retrieveValueAndDependenceInfo(rs, i, obj, values,
+              sizes, depClosures, depFieldIDs);
+        }
+        i++;
+      }
+
+      long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs,
+          values, sizes);
+
+      setID(id);
+    }
+
     private static void retrieveValueAndDependenceInfo(RenderScript rs,
         int index, Object obj, long[] values, int[] sizes, long[] depClosures,
         long[] depFieldIDs) {
@@ -102,6 +139,12 @@
         depClosures[index] = f.getClosure().getID(rs);
         Script.FieldID fieldID = f.getFieldID();
         depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
+        if (obj == null) {
+          // Value is originally created by the owner closure
+          values[index] = 0;
+          sizes[index] = 0;
+          return;
+        }
       } else {
         depClosures[index] = 0;
         depFieldIDs[index] = 0;
@@ -124,6 +167,10 @@
       Future f = mGlobalFuture.get(field);
 
       if (f == null) {
+        // If the field is not bound to this closure, this will return a future
+        // without an associated value (reference). So this is not working for
+        // cross-module (cross-script) linking in this case where a field not
+        // explicitly bound.
         f = new Future(this, field, mBindings.get(field));
         mGlobalFuture.put(field, f);
       }
@@ -163,7 +210,6 @@
           size = 8;
         }
       }
-
       public long value;
       public int size;
     }
@@ -240,12 +286,10 @@
     for (int i = 0; i < closureIDs.length; i++) {
       closureIDs[i] = closures.get(i).getID(rs);
     }
-    long id = rs.nScriptGroup2Create(closureIDs);
+    long id = rs.nScriptGroup2Create(ScriptC.mCachePath, closureIDs);
     setID(id);
   }
 
-  // TODO: If this was reflected method, we could enforce the number of
-  // arguments.
   public Object[] execute(Object... inputs) {
     if (inputs.length < mInputs.size()) {
       Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
@@ -302,6 +346,13 @@
       return c;
     }
 
+    public Closure addInvoke(Script.InvokeID invoke, Object[] args,
+        Map<Script.FieldID, Object> globalBindings) {
+      Closure c = new Closure(mRS, invoke, args, globalBindings);
+      mClosures.add(c);
+      return c;
+    }
+
     public UnboundValue addInput() {
       UnboundValue unbound = new UnboundValue();
       mInputs.add(unbound);
@@ -309,8 +360,6 @@
     }
 
     public ScriptGroup2 create(Future... outputs) {
-      // TODO: Save all script groups that have been created and return one that was
-      // saved and matches the outputs.
       ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs);
       return ret;
     }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 06f4def..b25dd41 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -242,6 +242,37 @@
       depFieldIDs, (size_t)depFieldIDs_length);
 }
 
+static jlong
+nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
+                     jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
+                     jintArray sizeArray) {
+  jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
+  jsize jParamLength = _env->GetArrayLength(paramArray);
+
+  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
+  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
+  RsScriptFieldID* fieldIDs =
+      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
+  for (int i = 0; i< fieldIDs_length; i++) {
+    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
+  }
+
+  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
+  jsize values_length = _env->GetArrayLength(valueArray);
+  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
+  for (int i = 0; i < values_length; i++) {
+    values[i] = (uintptr_t)jValues[i];
+  }
+
+  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
+  jsize sizes_length = _env->GetArrayLength(sizeArray);
+
+  return (jlong)(uintptr_t)rsInvokeClosureCreate(
+      (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
+      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
+      (size_t*)sizes, (size_t)sizes_length);
+}
+
 static void
 nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
                jint index, jlong value, jint size) {
@@ -258,7 +289,9 @@
 
 static long
 nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con,
-                    jlongArray closureArray) {
+                    jstring cacheDir, jlongArray closureArray) {
+  AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
+
   jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
   jsize numClosures = _env->GetArrayLength(closureArray);
   RsClosure* closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
@@ -266,8 +299,9 @@
     closures[i] = (RsClosure)jClosures[i];
   }
 
-  return (jlong)(uintptr_t)rsScriptGroup2Create((RsContext)con, closures,
-                                                numClosures);
+  return (jlong)(uintptr_t)rsScriptGroup2Create(
+      (RsContext)con, cacheDirUTF.c_str(), cacheDirUTF.length(),
+      closures, numClosures);
 }
 
 static void
@@ -1485,6 +1519,16 @@
 }
 
 static jlong
+nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
+{
+    if (kLogApi) {
+        ALOGD("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con,
+              (void *)sid, slot);
+    }
+    return (jlong)(uintptr_t)rsScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot);
+}
+
+static jlong
 nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
 {
     if (kLogApi) {
@@ -1932,6 +1976,7 @@
 {"rsnContextResume",                 "(J)V",                                  (void*)nContextResume },
 {"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
 {"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
+{"rsnInvokeClosureCreate",           "(JJ[B[J[J[I)J",                         (void*)nInvokeClosureCreate },
 {"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
 {"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
 {"rsnAssignName",                    "(JJ[B)V",                               (void*)nAssignName },
@@ -2006,9 +2051,10 @@
 {"rsnScriptCCreate",                 "(JLjava/lang/String;Ljava/lang/String;[BI)J",  (void*)nScriptCCreate },
 {"rsnScriptIntrinsicCreate",         "(JIJ)J",                                (void*)nScriptIntrinsicCreate },
 {"rsnScriptKernelIDCreate",          "(JJII)J",                               (void*)nScriptKernelIDCreate },
+{"rsnScriptInvokeIDCreate",          "(JJI)J",                                (void*)nScriptInvokeIDCreate },
 {"rsnScriptFieldIDCreate",           "(JJI)J",                                (void*)nScriptFieldIDCreate },
 {"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
-{"rsnScriptGroup2Create",            "(J[J)J",                                (void*)nScriptGroup2Create },
+{"rsnScriptGroup2Create",            "(JLjava/lang/String;[J)J",               (void*)nScriptGroup2Create },
 {"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
 {"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
 {"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 8c314cf..a712d78 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -170,6 +170,8 @@
 
     private final Rect mTempRect = new Rect();
 
+    private final Rect mTempRect1 = new Rect();
+
     private final Point mTempPoint = new Point();
 
     private final PackageManager mPackageManager;
@@ -2535,57 +2537,6 @@
         }
 
         @Override
-        public  boolean computeClickPointInScreen(int accessibilityWindowId,
-                long accessibilityNodeId, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
-                throws RemoteException {
-            final int resolvedWindowId;
-            IAccessibilityInteractionConnection connection = null;
-            Region partialInteractiveRegion = mTempRegion;
-            synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
-                    return false;
-                }
-                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
-                final boolean permissionGranted =
-                        mSecurityPolicy.canRetrieveWindowContentLocked(this);
-                if (!permissionGranted) {
-                    return false;
-                } else {
-                    connection = getConnectionLocked(resolvedWindowId);
-                    if (connection == null) {
-                        return false;
-                    }
-                }
-                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
-                        resolvedWindowId, partialInteractiveRegion)) {
-                    partialInteractiveRegion = null;
-                }
-            }
-            final int interrogatingPid = Binder.getCallingPid();
-            final long identityToken = Binder.clearCallingIdentity();
-            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
-            try {
-                connection.computeClickPointInScreen(accessibilityNodeId, partialInteractiveRegion,
-                        interactionId, callback, interrogatingPid, interrogatingTid, spec);
-                return true;
-            } catch (RemoteException re) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "Error computeClickPointInScreen().");
-                }
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-            return false;
-        }
-
-        @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
             synchronized (mLock) {
@@ -3238,38 +3189,36 @@
             }
 
             synchronized (mLock) {
-                Point point = mClient.computeClickPointInScreen(mConnectionId,
-                        focus.getWindowId(), focus.getSourceNodeId());
+                Rect boundsInScreen = mTempRect;
+                focus.getBoundsInScreen(boundsInScreen);
 
-                if (point == null) {
+                // Clip to the window bounds.
+                Rect windowBounds = mTempRect1;
+                getWindowBounds(focus.getWindowId(), windowBounds);
+                boundsInScreen.intersect(windowBounds);
+                if (boundsInScreen.isEmpty()) {
                     return false;
                 }
 
+                // Apply magnification if needed.
                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
                 if (spec != null && !spec.isNop()) {
-                    point.offset((int) -spec.offsetX, (int) -spec.offsetY);
-                    point.x = (int) (point.x * (1 / spec.scale));
-                    point.y = (int) (point.y * (1 / spec.scale));
+                    boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
+                    boundsInScreen.scale(1 / spec.scale);
                 }
 
-                // Make sure the point is within the window.
-                Rect windowBounds = mTempRect;
-                getWindowBounds(focus.getWindowId(), windowBounds);
-                if (!windowBounds.contains(point.x, point.y)) {
-                    return false;
-                }
-
-                // Make sure the point is within the screen.
+                // Clip to the screen bounds.
                 Point screenSize = mTempPoint;
                 mDefaultDisplay.getRealSize(screenSize);
-                if (point.x < 0 || point.x > screenSize.x
-                        || point.y < 0 || point.y > screenSize.y) {
+                boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y);
+                if (boundsInScreen.isEmpty()) {
                     return false;
                 }
 
-                outPoint.set(point.x, point.y);
-                return true;
+                outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
             }
+
+            return true;
         }
 
         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index b9ed89b..f18b5ef 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -77,6 +77,10 @@
     private static final int STATE_DELEGATING = 0x00000004;
     private static final int STATE_GESTURE_DETECTING = 0x00000005;
 
+    private static final int CLICK_LOCATION_NONE = 0;
+    private static final int CLICK_LOCATION_ACCESSIBILITY_FOCUS = 1;
+    private static final int CLICK_LOCATION_LAST_TOUCH_EXPLORED = 2;
+
     // The maximum of the cosine between the vectors of two moving
     // pointers so they can be considered moving in the same direction.
     private static final float MAX_DRAGGING_ANGLE_COS = 0.525321989f; // cos(pi/4)
@@ -942,12 +946,16 @@
      *
      * @param prototype The prototype from which to create the injected events.
      * @param policyFlags The policy flags associated with the event.
+     * @param targetAccessibilityFocus Whether the event targets the accessibility focus.
      */
-    private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
+    private void sendActionDownAndUp(MotionEvent prototype, int policyFlags,
+            boolean targetAccessibilityFocus) {
         // Tap with the pointer that last explored.
         final int pointerId = prototype.getPointerId(prototype.getActionIndex());
         final int pointerIdBits = (1 << pointerId);
+        prototype.setTargetAccessibilityFocus(targetAccessibilityFocus);
         sendMotionEvent(prototype, MotionEvent.ACTION_DOWN, pointerIdBits, policyFlags);
+        prototype.setTargetAccessibilityFocus(targetAccessibilityFocus);
         sendMotionEvent(prototype, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
     }
 
@@ -1155,7 +1163,8 @@
             final int pointerIndex = secondTapUp.findPointerIndex(pointerId);
 
             Point clickLocation = mTempPoint;
-            if (!computeClickLocation(clickLocation)) {
+            final int result = computeClickLocation(clickLocation);
+            if (result == CLICK_LOCATION_NONE) {
                 return;
             }
 
@@ -1171,7 +1180,8 @@
                     secondTapUp.getEventTime(), MotionEvent.ACTION_DOWN, 1, properties,
                     coords, 0, 0, 1.0f, 1.0f, secondTapUp.getDeviceId(), 0,
                     secondTapUp.getSource(), secondTapUp.getFlags());
-            sendActionDownAndUp(event, policyFlags);
+            final boolean targetAccessibilityFocus = (result == CLICK_LOCATION_ACCESSIBILITY_FOCUS);
+            sendActionDownAndUp(event, policyFlags, targetAccessibilityFocus);
             event.recycle();
         }
 
@@ -1216,7 +1226,7 @@
                 MAX_DRAGGING_ANGLE_COS);
     }
 
-    private boolean computeClickLocation(Point outLocation) {
+    private int computeClickLocation(Point outLocation) {
         MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEventForClick();
         if (lastExploreEvent != null) {
             final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
@@ -1224,14 +1234,17 @@
             outLocation.y = (int) lastExploreEvent.getY(lastExplorePointerIndex);
             if (!mAms.accessibilityFocusOnlyInActiveWindow()
                     || mLastTouchedWindowId == mAms.getActiveWindowId()) {
-                mAms.getAccessibilityFocusClickPointInScreen(outLocation);
+                if (mAms.getAccessibilityFocusClickPointInScreen(outLocation)) {
+                    return CLICK_LOCATION_ACCESSIBILITY_FOCUS;
+                } else {
+                    return CLICK_LOCATION_LAST_TOUCH_EXPLORED;
+                }
             }
-            return true;
         }
         if (mAms.getAccessibilityFocusClickPointInScreen(outLocation)) {
-            return true;
+            return CLICK_LOCATION_ACCESSIBILITY_FOCUS;
         }
-        return false;
+        return CLICK_LOCATION_NONE;
     }
 
     /**
@@ -1310,14 +1323,13 @@
                 return;
             }
 
-            int clickLocationX;
-            int clickLocationY;
-
             final int pointerId = mEvent.getPointerId(mEvent.getActionIndex());
             final int pointerIndex = mEvent.findPointerIndex(pointerId);
 
             Point clickLocation = mTempPoint;
-            if (!computeClickLocation(clickLocation)) {
+            final int result = computeClickLocation(clickLocation);
+
+            if (result == CLICK_LOCATION_NONE) {
                 return;
             }
 
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 289152b..c1e4994 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -382,6 +382,7 @@
                     // we're now good to go, so start the backup alarms
                     if (MORE_DEBUG) Slog.d(TAG, "Now provisioned, so starting backups");
                     startBackupAlarmsLocked(FIRST_BACKUP_INTERVAL);
+                    scheduleNextFullBackupJob();
                 }
             }
         }
@@ -3853,6 +3854,16 @@
             PackageInfo currentPackage;
 
             try {
+                if (!mEnabled || !mProvisioned) {
+                    // Backups are globally disabled, so don't proceed.
+                    if (DEBUG) {
+                        Slog.i(TAG, "full backup requested but e=" + mEnabled
+                                + " p=" + mProvisioned + "; ignoring");
+                    }
+                    mUpdateSchedule = false;
+                    return;
+                }
+
                 IBackupTransport transport = getTransport(mCurrentTransport);
                 if (transport == null) {
                     Slog.w(TAG, "Transport not present; full data backup not performed");
@@ -4150,6 +4161,17 @@
         long now = System.currentTimeMillis();
         FullBackupEntry entry = null;
 
+        if (!mEnabled || !mProvisioned) {
+            // Backups are globally disabled, so don't proceed.  We also don't reschedule
+            // the job driving automatic backups; that job will be scheduled again when
+            // the user enables backup.
+            if (MORE_DEBUG) {
+                Slog.i(TAG, "beginFullBackup but e=" + mEnabled
+                        + " p=" + mProvisioned + "; ignoring");
+            }
+            return false;
+        }
+
         if (DEBUG_SCHEDULING) {
             Slog.i(TAG, "Beginning scheduled full backup operation");
         }
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 45fa373..7d156df 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1230,7 +1230,8 @@
         if (mAlarmBatches.size() > 0) {
             final Batch firstWakeup = findFirstWakeupBatchLocked();
             final Batch firstBatch = mAlarmBatches.get(0);
-            if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
+            // always update the kernel alarms, as a backstop against missed wakeups
+            if (firstWakeup != null) {
                 mNextWakeup = firstWakeup.start;
                 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
             }
@@ -1243,7 +1244,8 @@
                 nextNonWakeup = mNextNonWakeupDeliveryTime;
             }
         }
-        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+        // always update the kernel alarm, as a backstop against missed wakeups
+        if (nextNonWakeup != 0) {
             mNextNonWakeup = nextNonWakeup;
             setLocked(ELAPSED_REALTIME, nextNonWakeup);
         }
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index bffbb4c2..c9a83ec 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -219,6 +219,7 @@
 
         mWakeLock.acquire();
 
+        Log.i(TAG, "MSG_NEW_DEVICE_STATE ");
         Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
                 mHeadsetState, newName);
         mHandler.sendMessage(msg);
@@ -286,14 +287,16 @@
                 return;
             }
 
-            if (LOG)
-                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
+            if (LOG) {
+                Slog.v(TAG, "headsetName: " + headsetName +
+                        (state == 1 ? " connected" : " disconnected"));
+            }
 
             if (outDevice != 0) {
-              mAudioManager.setWiredDeviceConnectionState(outDevice, state, headsetName);
+              mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName);
             }
             if (inDevice != 0) {
-              mAudioManager.setWiredDeviceConnectionState(inDevice, state, headsetName);
+              mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b5d2720..7a493c6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -87,6 +87,7 @@
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.WindowManagerService;
+
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -169,6 +170,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPermissionController;
+import android.os.IProcessInfoService;
 import android.os.IRemoteCallback;
 import android.os.IUserManager;
 import android.os.Looper;
@@ -1854,9 +1856,14 @@
                     synchronized (ActivityManagerService.this) {
                         if (DEBUG_PSS) Slog.d(TAG, "Collected native and kernel memory in "
                                 + (SystemClock.uptimeMillis()-start) + "ms");
-                        mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(),
-                                memInfo.getFreeSizeKb(), memInfo.getZramTotalSizeKb(),
-                                memInfo.getKernelUsedSizeKb(), nativeTotalPss);
+                        final long cachedKb = memInfo.getCachedSizeKb();
+                        final long freeKb = memInfo.getFreeSizeKb();
+                        final long zramKb = memInfo.getZramTotalSizeKb();
+                        final long kernelKb = memInfo.getKernelUsedSizeKb();
+                        EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
+                                kernelKb*1024, nativeTotalPss*1024);
+                        mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
+                                nativeTotalPss);
                     }
                 }
 
@@ -1914,6 +1921,7 @@
                 ServiceManager.addService("cpuinfo", new CpuBinder(this));
             }
             ServiceManager.addService("permission", new PermissionController(this));
+            ServiceManager.addService("processinfo", new ProcessInfoService(this));
 
             ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                     "android", STOCK_PM_FLAGS);
@@ -5617,7 +5625,10 @@
 
     @Override
     public void showBootMessage(final CharSequence msg, final boolean always) {
-        enforceNotIsolatedCaller("showBootMessage");
+        if (Binder.getCallingUid() != Process.myUid()) {
+            // These days only the core system can call this, so apps can't get in
+            // the way of what we show about running them.
+        }
         mWindowManager.showBootMessage(msg, always);
     }
 
@@ -6278,7 +6289,46 @@
             }
         }
     }
-    
+
+    // =========================================================
+    // PROCESS INFO
+    // =========================================================
+
+    static class ProcessInfoService extends IProcessInfoService.Stub {
+        final ActivityManagerService mActivityManagerService;
+        ProcessInfoService(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        public void getProcessStatesFromPids(/*in*/ int[] pids, /*out*/ int[] states) {
+            mActivityManagerService.getProcessStatesForPIDs(/*in*/ pids, /*out*/ states);
+        }
+    }
+
+    /**
+     * For each PID in the given input array, write the current process state
+     * for that process into the output array, or -1 to indicate that no
+     * process with the given PID exists.
+     */
+    public void getProcessStatesForPIDs(/*in*/ int[] pids, /*out*/ int[] states) {
+        if (pids == null) {
+            throw new NullPointerException("pids");
+        } else if (states == null) {
+            throw new NullPointerException("states");
+        } else if (pids.length != states.length) {
+            throw new IllegalArgumentException("input and output arrays have different lengths!");
+        }
+
+        synchronized (mPidsSelfLocked) {
+            for (int i = 0; i < pids.length; i++) {
+                ProcessRecord pr = mPidsSelfLocked.get(pids[i]);
+                states[i] = (pr == null) ? ActivityManager.PROCESS_STATE_NONEXISTENT :
+                        pr.curProcState;
+            }
+        }
+    }
+
     // =========================================================
     // PERMISSIONS
     // =========================================================
@@ -7053,7 +7103,6 @@
                 return;
             }
 
-            final IPackageManager pm = AppGlobals.getPackageManager();
             final String authority = uri.getAuthority();
             final ProviderInfo pi = getProviderInfoLocked(authority, userId);
             if (pi == null) {
@@ -7822,6 +7871,18 @@
     }
 
     @Override
+    public void setTaskResizeable(int taskId, boolean resizeable) {
+        synchronized (this) {
+            TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+            if (task == null) {
+                Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
+                return;
+            }
+            task.mResizeable = resizeable;
+        }
+    }
+
+    @Override
     public Bitmap getTaskDescriptionIcon(String filename) {
         if (!FileUtils.isValidExtFilename(filename)
                 || !filename.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) {
@@ -8164,7 +8225,7 @@
     @Override
     public void resizeStack(int stackId, Rect bounds) {
         enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
-                "resizeStackBox()");
+                "resizeStack()");
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
@@ -10036,7 +10097,7 @@
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(true);
                 if (translucentChanged) {
-                    r.task.stack.releaseBackgroundResources();
+                    r.task.stack.releaseBackgroundResources(r);
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                 }
                 mWindowManager.setAppFullscreen(token, true);
@@ -10063,7 +10124,7 @@
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(false);
                 if (translucentChanged) {
-                    r.task.stack.convertToTranslucent(r);
+                    r.task.stack.convertActivityToTranslucent(r);
                 }
                 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                 mWindowManager.setAppFullscreen(token, false);
@@ -10580,9 +10641,68 @@
         }
     }
 
+    final class PreBootContinuation extends IIntentReceiver.Stub {
+        final Intent intent;
+        final Runnable onFinishCallback;
+        final ArrayList<ComponentName> doneReceivers;
+        final List<ResolveInfo> ris;
+        final int[] users;
+        int lastRi = -1;
+        int curRi = 0;
+        int curUser = 0;
+
+        PreBootContinuation(Intent _intent, Runnable _onFinishCallback,
+                ArrayList<ComponentName> _doneReceivers, List<ResolveInfo> _ris, int[] _users) {
+            intent = _intent;
+            onFinishCallback = _onFinishCallback;
+            doneReceivers = _doneReceivers;
+            ris = _ris;
+            users = _users;
+        }
+
+        void go() {
+            if (lastRi != curRi) {
+                ActivityInfo ai = ris.get(curRi).activityInfo;
+                ComponentName comp = new ComponentName(ai.packageName, ai.name);
+                intent.setComponent(comp);
+                doneReceivers.add(comp);
+                lastRi = curRi;
+                CharSequence label = ai.loadLabel(mContext.getPackageManager());
+                showBootMessage(mContext.getString(R.string.android_preparing_apk, label), false);
+            }
+            Slog.i(TAG, "Pre-boot of " + intent.getComponent().toShortString()
+                    + " for user " + users[curUser]);
+            EventLogTags.writeAmPreBoot(users[curUser], intent.getComponent().getPackageName());
+            broadcastIntentLocked(null, null, intent, null, this,
+                    0, null, null, null, AppOpsManager.OP_NONE,
+                    true, false, MY_PID, Process.SYSTEM_UID,
+                    users[curUser]);
+        }
+
+        public void performReceive(Intent intent, int resultCode,
+                String data, Bundle extras, boolean ordered,
+                boolean sticky, int sendingUser) {
+            curUser++;
+            if (curUser >= users.length) {
+                curUser = 0;
+                curRi++;
+                if (curRi >= ris.size()) {
+                    // All done sending broadcasts!
+                    if (onFinishCallback != null) {
+                        // The raw IIntentReceiver interface is called
+                        // with the AM lock held, so redispatch to
+                        // execute our code without the lock.
+                        mHandler.post(onFinishCallback);
+                    }
+                    return;
+                }
+            }
+            go();
+        }
+    }
+
     private boolean deliverPreBootCompleted(final Runnable onFinishCallback,
             ArrayList<ComponentName> doneReceivers, int userId) {
-        boolean waitingUpdate = false;
         Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
         List<ResolveInfo> ris = null;
         try {
@@ -10590,71 +10710,51 @@
                     intent, null, 0, userId);
         } catch (RemoteException e) {
         }
-        if (ris != null) {
-            for (int i=ris.size()-1; i>=0; i--) {
-                if ((ris.get(i).activityInfo.applicationInfo.flags
-                        &ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    ris.remove(i);
-                }
+        if (ris == null) {
+            return false;
+        }
+        for (int i=ris.size()-1; i>=0; i--) {
+            if ((ris.get(i).activityInfo.applicationInfo.flags
+                    &ApplicationInfo.FLAG_SYSTEM) == 0) {
+                ris.remove(i);
             }
-            intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
+        }
+        intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
 
-            // For User 0, load the version number. When delivering to a new user, deliver
-            // to all receivers.
-            if (userId == UserHandle.USER_OWNER) {
-                ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
-                for (int i=0; i<ris.size(); i++) {
-                    ActivityInfo ai = ris.get(i).activityInfo;
-                    ComponentName comp = new ComponentName(ai.packageName, ai.name);
-                    if (lastDoneReceivers.contains(comp)) {
-                        // We already did the pre boot receiver for this app with the current
-                        // platform version, so don't do it again...
-                        ris.remove(i);
-                        i--;
-                        // ...however, do keep it as one that has been done, so we don't
-                        // forget about it when rewriting the file of last done receivers.
-                        doneReceivers.add(comp);
-                    }
-                }
-            }
-
-            // If primary user, send broadcast to all available users, else just to userId
-            final int[] users = userId == UserHandle.USER_OWNER ? getUsersLocked()
-                    : new int[] { userId };
-            for (int i = 0; i < ris.size(); i++) {
+        // For User 0, load the version number. When delivering to a new user, deliver
+        // to all receivers.
+        if (userId == UserHandle.USER_OWNER) {
+            ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
+            for (int i=0; i<ris.size(); i++) {
                 ActivityInfo ai = ris.get(i).activityInfo;
                 ComponentName comp = new ComponentName(ai.packageName, ai.name);
-                doneReceivers.add(comp);
-                intent.setComponent(comp);
-                for (int j=0; j<users.length; j++) {
-                    IIntentReceiver finisher = null;
-                    // On last receiver and user, set up a completion callback
-                    if (i == ris.size() - 1 && j == users.length - 1 && onFinishCallback != null) {
-                        finisher = new IIntentReceiver.Stub() {
-                            public void performReceive(Intent intent, int resultCode,
-                                    String data, Bundle extras, boolean ordered,
-                                    boolean sticky, int sendingUser) {
-                                // The raw IIntentReceiver interface is called
-                                // with the AM lock held, so redispatch to
-                                // execute our code without the lock.
-                                mHandler.post(onFinishCallback);
-                            }
-                        };
-                    }
-                    Slog.i(TAG, "Sending system update to " + intent.getComponent()
-                            + " for user " + users[j]);
-                    broadcastIntentLocked(null, null, intent, null, finisher,
-                            0, null, null, null, AppOpsManager.OP_NONE,
-                            true, false, MY_PID, Process.SYSTEM_UID,
-                            users[j]);
-                    if (finisher != null) {
-                        waitingUpdate = true;
-                    }
+                if (false && lastDoneReceivers.contains(comp)) {
+                    // We already did the pre boot receiver for this app with the current
+                    // platform version, so don't do it again...
+                    ris.remove(i);
+                    i--;
+                    // ...however, do keep it as one that has been done, so we don't
+                    // forget about it when rewriting the file of last done receivers.
+                    doneReceivers.add(comp);
                 }
             }
         }
 
-        return waitingUpdate;
+        if (ris.size() <= 0) {
+            return false;
+        }
+
+        // If primary user, send broadcast to all available users, else just to userId
+        final int[] users = userId == UserHandle.USER_OWNER ? getUsersLocked()
+                : new int[] { userId };
+        if (users.length <= 0) {
+            return false;
+        }
+
+        PreBootContinuation cont = new PreBootContinuation(intent, onFinishCallback, doneReceivers,
+                ris, users);
+        cont.go();
+        return true;
     }
 
     public void systemReady(final Runnable goingCallback) {
@@ -10689,10 +10789,10 @@
                         synchronized (ActivityManagerService.this) {
                             mDidUpdate = true;
                         }
-                        writeLastDonePreBootReceivers(doneReceivers);
                         showBootMessage(mContext.getText(
                                 R.string.android_upgrading_complete),
                                 false);
+                        writeLastDonePreBootReceivers(doneReceivers);
                         systemReady(goingCallback);
                     }
                 }, doneReceivers, UserHandle.USER_OWNER);
@@ -13860,9 +13960,14 @@
             memInfo.readMemInfo();
             if (nativeProcTotalPss > 0) {
                 synchronized (this) {
-                    mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(),
-                            memInfo.getFreeSizeKb(), memInfo.getZramTotalSizeKb(),
-                            memInfo.getKernelUsedSizeKb(), nativeProcTotalPss);
+                    final long cachedKb = memInfo.getCachedSizeKb();
+                    final long freeKb = memInfo.getFreeSizeKb();
+                    final long zramKb = memInfo.getZramTotalSizeKb();
+                    final long kernelKb = memInfo.getKernelUsedSizeKb();
+                    EventLogTags.writeAmMeminfo(cachedKb*1024, freeKb*1024, zramKb*1024,
+                            kernelKb*1024, nativeProcTotalPss*1024);
+                    mProcessStats.addSysMemUsageLocked(cachedKb, freeKb, zramKb, kernelKb,
+                            nativeProcTotalPss);
                 }
             }
             if (!brief) {
@@ -14996,30 +15101,6 @@
     // BROADCASTS
     // =========================================================
 
-    private final List getStickiesLocked(String action, IntentFilter filter,
-            List cur, int userId) {
-        final ContentResolver resolver = mContext.getContentResolver();
-        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
-        if (stickies == null) {
-            return cur;
-        }
-        final ArrayList<Intent> list = stickies.get(action);
-        if (list == null) {
-            return cur;
-        }
-        int N = list.size();
-        for (int i=0; i<N; i++) {
-            Intent intent = list.get(i);
-            if (filter.match(resolver, intent, true, TAG) >= 0) {
-                if (cur == null) {
-                    cur = new ArrayList<Intent>();
-                }
-                cur.add(intent);
-            }
-        }
-        return cur;
-    }
-
     boolean isPendingBroadcastProcessLocked(int pid) {
         return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
                 || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid);
@@ -15044,10 +15125,11 @@
     public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
         enforceNotIsolatedCaller("registerReceiver");
+        ArrayList<Intent> stickyIntents = null;
+        ProcessRecord callerApp = null;
         int callingUid;
         int callingPid;
         synchronized(this) {
-            ProcessRecord callerApp = null;
             if (caller != null) {
                 callerApp = getRecordForAppLocked(caller);
                 if (callerApp == null) {
@@ -15070,39 +15152,66 @@
                 callingPid = Binder.getCallingPid();
             }
 
-            userId = this.handleIncomingUser(callingPid, callingUid, userId,
+            userId = handleIncomingUser(callingPid, callingUid, userId,
                     true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
 
-            List allSticky = null;
+            Iterator<String> actions = filter.actionsIterator();
+            if (actions == null) {
+                ArrayList<String> noAction = new ArrayList<String>(1);
+                noAction.add(null);
+                actions = noAction.iterator();
+            }
 
-            // Look for any matching sticky broadcasts...
-            Iterator actions = filter.actionsIterator();
-            if (actions != null) {
-                while (actions.hasNext()) {
-                    String action = (String)actions.next();
-                    allSticky = getStickiesLocked(action, filter, allSticky,
-                            UserHandle.USER_ALL);
-                    allSticky = getStickiesLocked(action, filter, allSticky,
-                            UserHandle.getUserId(callingUid));
+            // Collect stickies of users
+            int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
+            while (actions.hasNext()) {
+                String action = actions.next();
+                for (int id : userIds) {
+                    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
+                    if (stickies != null) {
+                        ArrayList<Intent> intents = stickies.get(action);
+                        if (intents != null) {
+                            if (stickyIntents == null) {
+                                stickyIntents = new ArrayList<Intent>();
+                            }
+                            stickyIntents.addAll(intents);
+                        }
+                    }
                 }
-            } else {
-                allSticky = getStickiesLocked(null, filter, allSticky,
-                        UserHandle.USER_ALL);
-                allSticky = getStickiesLocked(null, filter, allSticky,
-                        UserHandle.getUserId(callingUid));
             }
+        }
 
-            // The first sticky in the list is returned directly back to
-            // the client.
-            Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
-
-            if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
-                    + ": " + sticky);
-
-            if (receiver == null) {
-                return sticky;
+        ArrayList<Intent> allSticky = null;
+        if (stickyIntents != null) {
+            final ContentResolver resolver = mContext.getContentResolver();
+            // Look for any matching sticky broadcasts...
+            for (int i = 0, N = stickyIntents.size(); i < N; i++) {
+                Intent intent = stickyIntents.get(i);
+                // If intent has scheme "content", it will need to acccess
+                // provider that needs to lock mProviderMap in ActivityThread
+                // and also it may need to wait application response, so we
+                // cannot lock ActivityManagerService here.
+                if (filter.match(resolver, intent, true, TAG) >= 0) {
+                    if (allSticky == null) {
+                        allSticky = new ArrayList<Intent>();
+                    }
+                    allSticky.add(intent);
+                }
             }
+        }
 
+        // The first sticky in the list is returned directly back to the client.
+        Intent sticky = allSticky != null ? allSticky.get(0) : null;
+        if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter + ": " + sticky);
+        if (receiver == null) {
+            return sticky;
+        }
+
+        synchronized (this) {
+            if (callerApp != null && callerApp.pid == 0) {
+                // Caller already died
+                return null;
+            }
             ReceiverList rl
                 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
             if (rl == null) {
@@ -15741,14 +15850,14 @@
                     callerPackage, callingPid, callingUid, resolvedType,
                     requiredPermission, appOp, receivers, resultTo, resultCode,
                     resultData, map, ordered, sticky, false, userId);
+
             if (DEBUG_BROADCAST) Slog.v(
                     TAG, "Enqueueing ordered broadcast " + r
                     + ": prev had " + queue.mOrderedBroadcasts.size());
-            if (DEBUG_BROADCAST) {
-                int seq = r.intent.getIntExtra("seq", -1);
-                Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
-            }
-            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r); 
+            if (DEBUG_BROADCAST) Slog.i(
+                    TAG, "Enqueueing broadcast " + r.intent.getAction());
+
+            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
             if (!replaced) {
                 queue.enqueueOrderedBroadcastLocked(r);
                 queue.scheduleBroadcastsLocked();
@@ -16079,6 +16188,15 @@
         return mStackSupervisor.getFocusedStack();
     }
 
+    @Override
+    public int getFocusedStackId() throws RemoteException {
+        ActivityStack focusedStack = getFocusedStack();
+        if (focusedStack != null) {
+            return focusedStack.getStackId();
+        }
+        return -1;
+    }
+
     public Configuration getConfiguration() {
         Configuration ci;
         synchronized(this) {
@@ -16255,7 +16373,8 @@
      */
     private static final boolean shouldShowDialogs(Configuration config) {
         return !(config.keyboard == Configuration.KEYBOARD_NOKEYS
-                && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH);
+                && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
+                && config.navigation == Configuration.NAVIGATION_NONAV);
     }
 
     /**
@@ -17056,6 +17175,7 @@
      * Record new PSS sample for a process.
      */
     void recordPssSample(ProcessRecord proc, int procState, long pss, long uss, long now) {
+        EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss*1024, uss*1024);
         proc.lastPssTime = now;
         proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList);
         if (DEBUG_PSS) Slog.d(TAG, "PSS of " + proc.toShortString()
@@ -18309,8 +18429,8 @@
         }
     }
 
-    private Set getProfileIdsLocked(int userId) {
-        Set userIds = new HashSet<Integer>();
+    private Set<Integer> getProfileIdsLocked(int userId) {
+        Set<Integer> userIds = new HashSet<Integer>();
         final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
                 userId, false /* enabledOnly */);
         for (UserInfo user : profiles) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a3676f9..b3f47e9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -75,7 +75,6 @@
     static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE;
     final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
 
-    private static final String TAG_ACTIVITY = "activity";
     private static final String ATTR_ID = "id";
     private static final String TAG_INTENT = "intent";
     private static final String ATTR_USERID = "user_id";
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index dbd787b..19f6e5a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -220,6 +220,9 @@
      */
     boolean mConfigWillChange;
 
+    // Whether or not this stack covers the entire screen; by default stacks are full screen
+    boolean mFullscreen = true;
+
     long mLaunchStartTime = 0;
     long mFullyDrawnStartTime = 0;
 
@@ -236,6 +239,9 @@
     final ActivityStackSupervisor mStackSupervisor;
 
     Configuration mOverrideConfig;
+    /** True if the stack was forced to full screen because {@link TaskRecord#mResizeable} is false
+     * and the stack was previously resized. */
+    private boolean mForcedFullscreen = false;
 
     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
@@ -1125,7 +1131,8 @@
 
         final int numStacks = mStacks.size();
         while (stackNdx < numStacks) {
-            tasks = mStacks.get(stackNdx).mTaskHistory;
+            ActivityStack historyStack = mStacks.get(stackNdx);
+            tasks = historyStack.mTaskHistory;
             final int numTasks = tasks.size();
             while (taskNdx < numTasks) {
                 activities = tasks.get(taskNdx).mActivities;
@@ -1133,7 +1140,7 @@
                 while (activityNdx < numActivities) {
                     final ActivityRecord activity = activities.get(activityNdx);
                     if (!activity.finishing) {
-                        return activity.fullscreen ? null : activity;
+                        return historyStack.mFullscreen && activity.fullscreen ? null : activity;
                     }
                     ++activityNdx;
                 }
@@ -1149,7 +1156,7 @@
 
     // Checks if any of the stacks above this one has a fullscreen activity behind it.
     // If so, this stack is hidden, otherwise it is visible.
-    private boolean isStackVisible() {
+    private boolean isStackVisibleLocked() {
         if (!isAttached()) {
             return false;
         }
@@ -1164,11 +1171,18 @@
          * wallpaper to be shown behind it.
          */
         for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
-            final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
-            for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
+            ActivityStack stack = mStacks.get(i);
+            // stack above isn't full screen, so, we assume we're still visible. at some point
+            // we should look at the stack bounds to see if we're occluded even if the stack
+            // isn't fullscreen
+            if (!stack.mFullscreen) {
+                continue;
+            }
+            final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                 final TaskRecord task = tasks.get(taskNdx);
                 final ArrayList<ActivityRecord> activities = task.mActivities;
-                for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
+                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                     final ActivityRecord r = activities.get(activityNdx);
 
                     // Conditions for an activity to obscure the stack we're
@@ -1214,7 +1228,7 @@
         // If the top activity is not fullscreen, then we need to
         // make sure any activities under it are now visible.
         boolean aboveTop = true;
-        boolean behindFullscreen = !isStackVisible();
+        boolean behindFullscreen = !isStackVisibleLocked();
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -1337,7 +1351,7 @@
                                     // This case created for transitioning activities from
                                     // translucent to opaque {@link Activity#convertToOpaque}.
                                     if (getVisibleBehindActivity() == r) {
-                                        releaseBackgroundResources();
+                                        releaseBackgroundResources(r);
                                     } else {
                                         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
                                             mStackSupervisor.mStoppingActivities.add(r);
@@ -1369,7 +1383,7 @@
         }
     }
 
-    void convertToTranslucent(ActivityRecord r) {
+    void convertActivityToTranslucent(ActivityRecord r) {
         mTranslucentActivityWaiting = r;
         mUndrawnActivitiesBelowTopTranslucent.clear();
         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
@@ -1905,9 +1919,31 @@
         return true;
     }
 
+    private TaskRecord getNextTask(TaskRecord targetTask) {
+        final int index = mTaskHistory.indexOf(targetTask);
+        if (index >= 0) {
+            final int numTasks = mTaskHistory.size();
+            for (int i = index + 1; i < numTasks; ++i) {
+                TaskRecord task = mTaskHistory.get(i);
+                if (task.userId == targetTask.userId) {
+                    return task;
+                }
+            }
+        }
+        return null;
+    }
+
     private void insertTaskAtTop(TaskRecord task) {
+        // If the moving task is over home stack, transfer its return type to next task
+        if (task.isOverHomeStack()) {
+            final TaskRecord nextTask = getNextTask(task);
+            if (nextTask != null) {
+                nextTask.setTaskToReturnTo(task.getTaskToReturnTo());
+            }
+        }
+
         // If this is being moved to the top by another activity or being launched from the home
-        // activity, set mOnTopOfHome accordingly.
+        // activity, set mTaskToReturnTo accordingly.
         if (isOnHomeDisplay()) {
             ActivityStack lastStack = mStackSupervisor.getLastStack();
             final boolean fromHome = lastStack.isHomeStack();
@@ -3282,10 +3318,9 @@
         }
     }
 
-    void releaseBackgroundResources() {
+    void releaseBackgroundResources(ActivityRecord r) {
         if (hasVisibleBehindActivity() &&
                 !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
-            final ActivityRecord r = getVisibleBehindActivity();
             if (r == topRunningActivityLocked(null)) {
                 // Don't release the top activity if it has requested to run behind the next
                 // activity.
@@ -3567,6 +3602,15 @@
         if (DEBUG_TRANSITION) Slog.v(TAG,
                 "Prepare to back transition: task=" + taskId);
 
+        boolean prevIsHome = false;
+        if (tr.isOverHomeStack()) {
+            final TaskRecord nextTask = getNextTask(tr);
+            if (nextTask != null) {
+                nextTask.setTaskToReturnTo(tr.getTaskToReturnTo());
+            } else {
+                prevIsHome = true;
+            }
+        }
         mTaskHistory.remove(tr);
         mTaskHistory.add(0, tr);
         updateTaskMovement(tr, false);
@@ -3593,7 +3637,8 @@
         }
 
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
-        if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) {
+        if (prevIsHome || task == tr && tr.isOverHomeStack()
+                || numTasks <= 1 && isOnHomeDisplay()) {
             if (!mService.mBooting && !mService.mBooted) {
                 // Not ready yet!
                 return false;
@@ -3636,6 +3681,24 @@
         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
                 "Ensuring correct configuration: " + r);
 
+        // Make sure the current stack override configuration is supported by the top task
+        // before continuing.
+        final TaskRecord topTask = topTask();
+        if (topTask != null && ((topTask.mResizeable && mForcedFullscreen)
+                    || (!topTask.mResizeable && !mFullscreen))) {
+            final boolean prevFullscreen = mFullscreen;
+            final Configuration newOverrideConfig =
+                    mWindowManager.forceStackToFullscreen(mStackId, !topTask.mResizeable);
+            updateOverrideConfiguration(newOverrideConfig);
+            mForcedFullscreen = !prevFullscreen && mFullscreen;
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
+                    "Updated stack config to support task=" + topTask
+                            + " resizeable=" + topTask.mResizeable
+                            + " mForcedFullscreen=" + mForcedFullscreen
+                            + " prevFullscreen=" + prevFullscreen
+                            + " mFullscreen=" + mFullscreen);
+        }
+
         // Short circuit: if the two configurations are the exact same
         // object (the common case), then there is nothing to do.
         Configuration newConfig = mService.mConfiguration;
@@ -4111,7 +4174,7 @@
     }
 
     ArrayList<TaskRecord> getAllTasks() {
-        return new ArrayList<TaskRecord>(mTaskHistory);
+        return new ArrayList<>(mTaskHistory);
     }
 
     void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
@@ -4143,6 +4206,10 @@
     boolean updateOverrideConfiguration(Configuration newConfig) {
         Configuration oldConfig = mOverrideConfig;
         mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig;
+        // We override the configuration only when the stack's dimensions are different from
+        // the display. In this manner, we know that if the override configuration is empty,
+        // the stack is necessarily full screen.
+        mFullscreen = Configuration.EMPTY.equals(mOverrideConfig);
         return !mOverrideConfig.equals(oldConfig);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4674cc2..58104a8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2604,9 +2604,15 @@
             Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
             return;
         }
+
+        final ActivityRecord r = stack.topRunningActivityLocked(null);
+        if (r != null && !r.task.mResizeable) {
+            Slog.w(TAG, "resizeStack: top task " + r.task + " not resizeable.");
+            return;
+        }
+
         final Configuration overrideConfig = mWindowManager.resizeStack(stackId, bounds);
         if (stack.updateOverrideConfiguration(overrideConfig)) {
-            final ActivityRecord r = stack.topRunningActivityLocked(null);
             if (r != null) {
                 final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
                 // And we need to make sure at this point that all other activities
@@ -3752,6 +3758,13 @@
         }
 
         @Override
+        public int getStackId() {
+            synchronized (mService) {
+                return mStackId;
+            }
+        }
+
+        @Override
         public boolean injectEvent(InputEvent event) {
             final long origId = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 9b7d0b2..7ab3794 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -513,11 +513,7 @@
                 }
             }
             try {
-                if (DEBUG_BROADCAST_LIGHT) {
-                    int seq = r.intent.getIntExtra("seq", -1);
-                    Slog.i(TAG, "Delivering to " + filter
-                            + " (seq=" + seq + "): " + r);
-                }
+                if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG, "Delivering to " + filter + " : " + r);
                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                     new Intent(r.intent), r.resultCode, r.resultData,
                     r.resultExtras, r.ordered, r.initialSticky, r.userId);
@@ -662,12 +658,9 @@
                     // result if requested...
                     if (r.resultTo != null) {
                         try {
-                            if (DEBUG_BROADCAST) {
-                                int seq = r.intent.getIntExtra("seq", -1);
-                                Slog.i(TAG, "Finishing broadcast ["
-                                        + mQueueName + "] " + r.intent.getAction()
-                                        + " seq=" + seq + " app=" + r.callerApp);
-                            }
+                            if (DEBUG_BROADCAST) Slog.i(TAG,
+                                    "Finishing broadcast [" + mQueueName + "] "
+                                    + r.intent.getAction() + " app=" + r.callerApp);
                             performReceiveLocked(r.callerApp, r.resultTo,
                                 new Intent(r.intent), r.resultCode,
                                 r.resultData, r.resultExtras, false, false, r.userId);
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index c376744..9a645df 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -95,3 +95,11 @@
 
 # Home Stack brought to front or rear
 30044 am_home_stack_moved (User|1|5),(To Front|1|5),(Top Stack Id|1|5),(Focused Stack Id|1|5),(Reason|3)
+
+# Running pre boot receiver
+30045 am_pre_boot (User|1|5),(Package|3)
+
+# Report collection of global memory state
+30046 am_meminfo (CachedKb|2|2),(FreeKb|2|2),(ZramKb|2|2),(KernelKb|2|2),(NativeKb|2|2)
+# Report collection of memory used by a process
+30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(PssKb|2|2),(UssKb|2|2)
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 3011148..76bb498 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -79,6 +79,7 @@
     private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
     private static final String ATTR_CALLING_UID = "calling_uid";
     private static final String ATTR_CALLING_PACKAGE = "calling_package";
+    private static final String ATTR_RESIZEABLE = "resizeable";
 
     private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
 
@@ -109,10 +110,12 @@
 
     String stringName;      // caching of toString() result.
     int userId;             // user for which this task was created
-    int creatorUid;         // The app uid that originally created the task
 
     int numFullscreen;      // Number of fullscreen activities.
 
+    boolean mResizeable;    // Activities in the task resizeable. Based on the resizable setting of
+                            // the root activity.
+
     // This represents the last resolved activity values for this task
     // NOTE: This value needs to be persisted with each task
     TaskDescription lastTaskDescription = new TaskDescription();
@@ -176,7 +179,7 @@
         voiceSession = _voiceSession;
         voiceInteractor = _voiceInteractor;
         isAvailable = true;
-        mActivities = new ArrayList<ActivityRecord>();
+        mActivities = new ArrayList<>();
         setIntent(_intent, info);
     }
 
@@ -191,7 +194,7 @@
         voiceSession = null;
         voiceInteractor = null;
         isAvailable = true;
-        mActivities = new ArrayList<ActivityRecord>();
+        mActivities = new ArrayList<>();
         setIntent(_intent, info);
 
         taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
@@ -210,15 +213,15 @@
         mCallingPackage = info.packageName;
     }
 
-    TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
-            String _affinity, String _rootAffinity, ComponentName _realActivity,
-            ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
-            boolean _askedCompatMode, int _taskType, int _userId, int _effectiveUid,
-            String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
-            long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
-            TaskDescription _lastTaskDescription, int taskAffiliation,
-            int prevTaskId, int nextTaskId, int taskAffiliationColor, int callingUid,
-            String callingPackage) {
+    private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
+            Intent _affinityIntent, String _affinity, String _rootAffinity,
+            ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
+            boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId,
+            int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
+            long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
+            boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
+            int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
+            int callingUid, String callingPackage, boolean resizeable) {
         mService = service;
         mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
                 TaskPersister.IMAGE_EXTENSION;
@@ -227,7 +230,7 @@
         intent = _intent;
         affinityIntent = _affinityIntent;
         affinity = _affinity;
-        rootAffinity = _affinity;
+        rootAffinity = _rootAffinity;
         voiceSession = null;
         voiceInteractor = null;
         realActivity = _realActivity;
@@ -253,6 +256,7 @@
         mNextAffiliateTaskId = nextTaskId;
         mCallingUid = callingUid;
         mCallingPackage = callingPackage;
+        mResizeable = resizeable;
     }
 
     void touchActiveTime() {
@@ -352,6 +356,7 @@
         } else {
             autoRemoveRecents = false;
         }
+        mResizeable = info.resizeable;
     }
 
     void setTaskToReturnTo(int taskToReturnTo) {
@@ -850,6 +855,7 @@
         out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
         out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
         out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
+        out.attribute(null, ATTR_RESIZEABLE, String.valueOf(mResizeable));
 
         if (affinityIntent != null) {
             out.startTag(null, TAG_AFFINITYINTENT);
@@ -911,6 +917,7 @@
         int nextTaskId = INVALID_TASK_ID;
         int callingUid = -1;
         String callingPackage = "";
+        boolean resizeable = false;
 
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
@@ -964,6 +971,8 @@
                 callingUid = Integer.valueOf(attrValue);
             } else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
                 callingPackage = attrValue;
+            } else if (ATTR_RESIZEABLE.equals(attrName)) {
+                resizeable = Boolean.valueOf(attrValue);
             } else {
                 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
             }
@@ -993,13 +1002,11 @@
                 }
             }
         }
-
         if (!hasRootAffinity) {
             rootAffinity = affinity;
         } else if ("@".equals(rootAffinity)) {
             rootAffinity = null;
         }
-
         if (effectiveUid <= 0) {
             Intent checkIntent = intent != null ? intent : affinityIntent;
             effectiveUid = 0;
@@ -1025,7 +1032,7 @@
                 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
                 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                 taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
-                callingUid, callingPackage);
+                callingUid, callingPackage, resizeable);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
             activities.get(activityNdx).task = task;
@@ -1121,6 +1128,7 @@
             pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
         }
         pw.print(prefix); pw.print("hasBeenVisible="); pw.print(hasBeenVisible);
+                pw.print(" mResizeable="); pw.print(mResizeable);
                 pw.print(" firstActiveTime="); pw.print(lastActiveTime);
                 pw.print(" lastActiveTime="); pw.print(lastActiveTime);
                 pw.print(" (inactive for ");
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index f900d0d..87f78c1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -28,6 +28,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkRequest;
+import android.net.ProxyInfo;
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.net.wifi.WifiInfo;
@@ -656,12 +657,36 @@
         int httpResponseCode = 599;
         try {
             URL url = new URL("http", mServer, "/generate_204");
+            // On networks with a PAC instead of fetching a URL that should result in a 204
+            // reponse, we instead simply fetch the PAC script.  This is done for a few reasons:
+            // 1. At present our PAC code does not yet handle multiple PACs on multiple networks
+            //    until something like https://android-review.googlesource.com/#/c/115180/ lands.
+            //    Network.openConnection() will ignore network-specific PACs and instead fetch
+            //    using NO_PROXY.  If a PAC is in place, the only fetch we know will succeed with
+            //    NO_PROXY is the fetch of the PAC itself.
+            // 2. To proxy the generate_204 fetch through a PAC would require a number of things
+            //    happen before the fetch can commence, namely:
+            //        a) the PAC script be fetched
+            //        b) a PAC script resolver service be fired up and resolve mServer
+            //    Network validation could be delayed until these prerequisities are satisifed or
+            //    could simply be left to race them.  Neither is an optimal solution.
+            // 3. PAC scripts are sometimes used to block or restrict Internet access and may in
+            //    fact block fetching of the generate_204 URL which would lead to false negative
+            //    results for network validation.
+            boolean fetchPac = false;
+            {
+                final ProxyInfo proxyInfo = mNetworkAgentInfo.linkProperties.getHttpProxy();
+                if (proxyInfo != null && !Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) {
+                    url = new URL(proxyInfo.getPacFileUrl().toString());
+                    fetchPac = true;
+                }
+            }
             if (DBG) {
                 log("Checking " + url.toString() + " on " +
                         mNetworkAgentInfo.networkInfo.getExtraInfo());
             }
             urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
-            urlConnection.setInstanceFollowRedirects(false);
+            urlConnection.setInstanceFollowRedirects(fetchPac);
             urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
             urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
             urlConnection.setUseCaches(false);
@@ -695,6 +720,11 @@
                 httpResponseCode = 204;
             }
 
+            if (httpResponseCode == 200 && fetchPac) {
+                if (DBG) log("PAC fetch 200 response interpreted as 204 response.");
+                httpResponseCode = 204;
+            }
+
             sendNetworkConditionsBroadcast(true /* response received */,
                     httpResponseCode != 204 /* isCaptivePortal */,
                     requestTimestamp, responseTimestamp);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index ce52920..a8f6954 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -55,10 +55,6 @@
         mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
                 mAddress, mService.getVendorId()));
         startQueuedActions();
-
-        // Switch TV input after bootup.
-        setActiveSource(true);
-        maySendActiveSource(Constants.ADDR_TV);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 8241cdc..4f458e6 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -904,7 +904,7 @@
         // Note that we don't set any name to ARC.
         mService.getAudioManager().setWiredDeviceConnectionState(
                 AudioSystem.DEVICE_OUT_HDMI_ARC,
-                enabled ? 1 : 0, "");
+                enabled ? 1 : 0, "", "");
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 2a1f7d6..e41b3da 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -25,7 +25,6 @@
 import com.android.internal.R;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
 
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
@@ -72,7 +71,6 @@
 import android.provider.Telephony.Carriers;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.SmsMessage;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
@@ -91,7 +89,6 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Date;
-import java.util.List;
 import java.util.Map.Entry;
 import java.util.Properties;
 
@@ -395,7 +392,7 @@
 
     private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
         @Override
-        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
+        public void addGpsStatusListener(IGpsStatusListener listener) {
             mListenerHelper.addListener(listener);
         }
 
@@ -681,7 +678,7 @@
         mListenerHelper = new GpsStatusListenerHelper(mHandler) {
             @Override
             protected boolean isAvailableInPlatform() {
-                return GpsLocationProvider.isSupported();
+                return isSupported();
             }
 
             @Override
@@ -1027,6 +1024,9 @@
             if (mC2KServerHost != null) {
                 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
             }
+
+            mGpsMeasurementsProvider.onGpsEnabledChanged();
+            mGpsNavigationMessageProvider.onGpsEnabledChanged();
         } else {
             synchronized (mLock) {
                 mEnabled = false;
@@ -1060,6 +1060,9 @@
 
         // do this before releasing wakelock
         native_cleanup();
+
+        mGpsMeasurementsProvider.onGpsEnabledChanged();
+        mGpsNavigationMessageProvider.onGpsEnabledChanged();
     }
 
     @Override
@@ -1479,9 +1482,7 @@
         }
 
         if (wasNavigating != mNavigating) {
-            mListenerHelper.onGpsEnabledChanged(mNavigating);
-            mGpsMeasurementsProvider.onGpsEnabledChanged(mNavigating);
-            mGpsNavigationMessageProvider.onGpsEnabledChanged(mNavigating);
+            mListenerHelper.onStatusChanged(mNavigating);
 
             // send an intent to notify that the GPS has been enabled or disabled
             Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
diff --git a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java b/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
index 0514e0c..b327ca2 100644
--- a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
@@ -33,7 +33,7 @@
         extends RemoteListenerHelper<IGpsMeasurementsListener> {
     private static final String TAG = "GpsMeasurementsProvider";
 
-    public GpsMeasurementsProvider(Handler handler) {
+    protected GpsMeasurementsProvider(Handler handler) {
         super(handler, TAG);
     }
 
@@ -49,15 +49,19 @@
     }
 
     public void onCapabilitiesUpdated(boolean isGpsMeasurementsSupported) {
-        int status = isGpsMeasurementsSupported ?
-                GpsMeasurementsEvent.STATUS_READY :
-                GpsMeasurementsEvent.STATUS_NOT_SUPPORTED;
-        setSupported(isGpsMeasurementsSupported, new StatusChangedOperation(status));
+        setSupported(isGpsMeasurementsSupported);
+        updateResult();
+    }
+
+    public void onGpsEnabledChanged() {
+        if (tryUpdateRegistrationWithService()) {
+            updateResult();
+        }
     }
 
     @Override
     protected ListenerOperation<IGpsMeasurementsListener> getHandlerOperation(int result) {
-        final int status;
+        int status;
         switch (result) {
             case RESULT_SUCCESS:
                 status = GpsMeasurementsEvent.STATUS_READY;
@@ -70,6 +74,8 @@
             case RESULT_GPS_LOCATION_DISABLED:
                 status = GpsMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
                 break;
+            case RESULT_UNKNOWN:
+                return null;
             default:
                 Log.v(TAG, "Unhandled addListener result: " + result);
                 return null;
@@ -77,15 +83,8 @@
         return new StatusChangedOperation(status);
     }
 
-    @Override
-    protected void handleGpsEnabledChanged(boolean enabled) {
-        int status = enabled ?
-                GpsMeasurementsEvent.STATUS_READY :
-                GpsMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
-        foreach(new StatusChangedOperation(status));
-    }
-
-    private class StatusChangedOperation implements ListenerOperation<IGpsMeasurementsListener> {
+    private static class StatusChangedOperation
+            implements ListenerOperation<IGpsMeasurementsListener> {
         private final int mStatus;
 
         public StatusChangedOperation(int status) {
diff --git a/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java b/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
index 13d22fc..e6bbe56 100644
--- a/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
@@ -33,7 +33,7 @@
         extends RemoteListenerHelper<IGpsNavigationMessageListener> {
     private static final String TAG = "GpsNavigationMessageProvider";
 
-    public GpsNavigationMessageProvider(Handler handler) {
+    protected GpsNavigationMessageProvider(Handler handler) {
         super(handler, TAG);
     }
 
@@ -50,15 +50,19 @@
     }
 
     public void onCapabilitiesUpdated(boolean isGpsNavigationMessageSupported) {
-        int status = isGpsNavigationMessageSupported ?
-                GpsNavigationMessageEvent.STATUS_READY :
-                GpsNavigationMessageEvent.STATUS_NOT_SUPPORTED;
-        setSupported(isGpsNavigationMessageSupported, new StatusChangedOperation(status));
+        setSupported(isGpsNavigationMessageSupported);
+        updateResult();
+    }
+
+    public void onGpsEnabledChanged() {
+        if (tryUpdateRegistrationWithService()) {
+            updateResult();
+        }
     }
 
     @Override
     protected ListenerOperation<IGpsNavigationMessageListener> getHandlerOperation(int result) {
-        final int status;
+        int status;
         switch (result) {
             case RESULT_SUCCESS:
                 status = GpsNavigationMessageEvent.STATUS_READY;
@@ -71,6 +75,8 @@
             case RESULT_GPS_LOCATION_DISABLED:
                 status = GpsNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
                 break;
+            case RESULT_UNKNOWN:
+                return null;
             default:
                 Log.v(TAG, "Unhandled addListener result: " + result);
                 return null;
@@ -78,15 +84,7 @@
         return new StatusChangedOperation(status);
     }
 
-    @Override
-    protected void handleGpsEnabledChanged(boolean enabled) {
-        int status = enabled ?
-                GpsNavigationMessageEvent.STATUS_READY :
-                GpsNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
-        foreach(new StatusChangedOperation(status));
-    }
-
-    private class StatusChangedOperation
+    private static class StatusChangedOperation
             implements ListenerOperation<IGpsNavigationMessageListener> {
         private final int mStatus;
 
diff --git a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java b/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
index 376b4a5..53ff6c2 100644
--- a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
@@ -24,14 +24,9 @@
  * Implementation of a handler for {@link IGpsStatusListener}.
  */
 abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusListener> {
-    public GpsStatusListenerHelper(Handler handler) {
+    protected GpsStatusListenerHelper(Handler handler) {
         super(handler, "GpsStatusListenerHelper");
-
-        Operation nullOperation = new Operation() {
-            @Override
-            public void execute(IGpsStatusListener iGpsStatusListener) throws RemoteException {}
-        };
-        setSupported(GpsLocationProvider.isSupported(), nullOperation);
+        setSupported(GpsLocationProvider.isSupported());
     }
 
     @Override
@@ -47,10 +42,9 @@
         return null;
     }
 
-    @Override
-    protected void handleGpsEnabledChanged(boolean enabled) {
+    public void onStatusChanged(boolean isNavigating) {
         Operation operation;
-        if (enabled) {
+        if (isNavigating) {
             operation = new Operation() {
                 @Override
                 public void execute(IGpsStatusListener listener) throws RemoteException {
@@ -114,5 +108,5 @@
         foreach(operation);
     }
 
-    private abstract class Operation implements ListenerOperation<IGpsStatusListener> { }
+    private interface Operation extends ListenerOperation<IGpsStatusListener> {}
 }
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 402b601..ec2828b 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -26,26 +26,31 @@
 import android.util.Log;
 
 import java.util.HashMap;
+import java.util.Map;
 
 /**
  * A helper class, that handles operations in remote listeners, and tracks for remote process death.
  */
 abstract class RemoteListenerHelper<TListener extends IInterface> {
+
     protected static final int RESULT_SUCCESS = 0;
     protected static final int RESULT_NOT_AVAILABLE = 1;
     protected static final int RESULT_NOT_SUPPORTED = 2;
     protected static final int RESULT_GPS_LOCATION_DISABLED = 3;
     protected static final int RESULT_INTERNAL_ERROR = 4;
+    protected static final int RESULT_UNKNOWN = 5;
 
     private final Handler mHandler;
     private final String mTag;
 
-    private final HashMap<IBinder, LinkedListener> mListenerMap = new HashMap<>();
+    private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
 
     private boolean mIsRegistered;
     private boolean mHasIsSupported;
     private boolean mIsSupported;
 
+    private int mLastReportedResult = RESULT_UNKNOWN;
+
     protected RemoteListenerHelper(Handler handler, String name) {
         Preconditions.checkNotNull(name);
         mHandler = handler;
@@ -110,33 +115,11 @@
         }
     }
 
-    public void onGpsEnabledChanged(boolean enabled) {
-        // handle first the sub-class implementation, so any error in registration can take
-        // precedence
-        handleGpsEnabledChanged(enabled);
-        synchronized (mListenerMap) {
-            if (!enabled) {
-                tryUnregister();
-                return;
-            }
-            if (mListenerMap.isEmpty()) {
-                return;
-            }
-            if (tryRegister()) {
-                // registration was successful, there is no need to update the state
-                return;
-            }
-            ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
-            foreachUnsafe(operation);
-        }
-    }
-
     protected abstract boolean isAvailableInPlatform();
     protected abstract boolean isGpsEnabled();
     protected abstract boolean registerWithService();
     protected abstract void unregisterFromService();
     protected abstract ListenerOperation<TListener> getHandlerOperation(int result);
-    protected abstract void handleGpsEnabledChanged(boolean enabled);
 
     protected interface ListenerOperation<TListener extends IInterface> {
         void execute(TListener listener) throws RemoteException;
@@ -148,11 +131,40 @@
         }
     }
 
-    protected void setSupported(boolean value, ListenerOperation<TListener> notifier) {
+    protected void setSupported(boolean value) {
         synchronized (mListenerMap) {
             mHasIsSupported = true;
             mIsSupported = value;
-            foreachUnsafe(notifier);
+        }
+    }
+
+    protected boolean tryUpdateRegistrationWithService() {
+        synchronized (mListenerMap) {
+            if (!isGpsEnabled()) {
+                tryUnregister();
+                return true;
+            }
+            if (mListenerMap.isEmpty()) {
+                return true;
+            }
+            if (tryRegister()) {
+                // registration was successful, there is no need to update the state
+                return true;
+            }
+            ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
+            foreachUnsafe(operation);
+            return false;
+        }
+    }
+
+    protected void updateResult() {
+        synchronized (mListenerMap) {
+            int newResult = calculateCurrentResultUnsafe();
+            if (mLastReportedResult == newResult) {
+                return;
+            }
+            foreachUnsafe(getHandlerOperation(newResult));
+            mLastReportedResult = newResult;
         }
     }
 
@@ -183,6 +195,24 @@
         mIsRegistered = false;
     }
 
+    private int calculateCurrentResultUnsafe() {
+        // update statuses we already know about, starting from the ones that will never change
+        if (!isAvailableInPlatform()) {
+            return RESULT_NOT_AVAILABLE;
+        }
+        if (!mHasIsSupported || mListenerMap.isEmpty()) {
+            // we'll update once we have a supported status available
+            return RESULT_UNKNOWN;
+        }
+        if (!mIsSupported) {
+            return RESULT_NOT_SUPPORTED;
+        }
+        if (!isGpsEnabled()) {
+            return RESULT_GPS_LOCATION_DISABLED;
+        }
+        return RESULT_SUCCESS;
+    }
+
     private class LinkedListener implements IBinder.DeathRecipient {
         private final TListener mListener;
 
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index da63caa..df31158 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -250,77 +250,37 @@
         if (isPlaybackActive(false) || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
         }
-        boolean isMute = direction == MediaSessionManager.DIRECTION_MUTE;
-        if (direction > 1) {
-            direction = 1;
-        } else if (direction < -1) {
-            direction = -1;
-        }
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             if (mUseMasterVolume) {
                 // If this device only uses master volume and playback is local
                 // just adjust the master volume and return.
-                boolean isMasterMute = mAudioManager.isMasterMute();
-                if (isMute) {
-                    mAudioManagerInternal.setMasterMuteForUid(!isMasterMute,
-                            flags, packageName, mService.mICallback, uid);
-                } else {
-                    mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName,
-                            uid);
-                    if (isMasterMute) {
-                        mAudioManagerInternal.setMasterMuteForUid(false,
-                                flags, packageName, mService.mICallback, uid);
-                    }
-                }
+                mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName,
+                        uid);
                 return;
             }
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
-            boolean isStreamMute = mAudioManager.isStreamMute(stream);
             if (useSuggested) {
                 if (AudioSystem.isStreamActive(stream, 0)) {
-                    if (isMute) {
-                        mAudioManager.setStreamMute(stream, !isStreamMute);
-                    } else {
-                        mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction,
-                                flags, packageName, uid);
-                        if (isStreamMute && direction != 0) {
-                            mAudioManager.setStreamMute(stream, false);
-                        }
-                    }
+                    mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction,
+                            flags, packageName, uid);
                 } else {
                     flags |= previousFlagPlaySound;
-                    isStreamMute =
-                            mAudioManager.isStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE);
-                    if (isMute) {
-                        mAudioManager.setStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE,
-                                !isStreamMute);
-                    } else {
-                        mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
-                                AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName,
-                                uid);
-                        if (isStreamMute && direction != 0) {
-                            mAudioManager.setStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE,
-                                    false);
-                        }
-                    }
+                    mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
+                            AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName,
+                            uid);
                 }
             } else {
-                if (isMute) {
-                    mAudioManager.setStreamMute(stream, !isStreamMute);
-                } else {
-                    mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
-                            packageName, uid);
-                    if (isStreamMute && direction != 0) {
-                        mAudioManager.setStreamMute(stream, false);
-                    }
-                }
+                mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
+                        packageName, uid);
             }
         } else {
             if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
                 // Nothing to do, the volume cannot be changed
                 return;
             }
-            if (isMute) {
+            if (direction == AudioManager.ADJUST_TOGGLE_MUTE
+                    || direction == AudioManager.ADJUST_MUTE
+                    || direction == AudioManager.ADJUST_UNMUTE) {
                 Log.w(TAG, "Muting remote playback is not supported");
                 return;
             }
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 667d02a..4f6b8f2 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -823,7 +823,7 @@
                 pw.println("User Records:");
                 count = mUserRecords.size();
                 for (int i = 0; i < count; i++) {
-                    UserRecord user = mUserRecords.get(i);
+                    UserRecord user = mUserRecords.get(mUserRecords.keyAt(i));
                     user.dumpLocked(pw, "");
                 }
             }
@@ -872,30 +872,10 @@
                 try {
                     String packageName = getContext().getOpPackageName();
                     if (mUseMasterVolume) {
-                        boolean isMasterMute = mAudioService.isMasterMute();
-                        if (direction == MediaSessionManager.DIRECTION_MUTE) {
-                            mAudioService.setMasterMute(!isMasterMute, flags, packageName, mICallback);
-                        } else {
                             mAudioService.adjustMasterVolume(direction, flags, packageName);
-                            // Do not call setMasterMute when direction = 0 which is used just to
-                            // show the UI.
-                            if (isMasterMute && direction != 0) {
-                                mAudioService.setMasterMute(false, flags, packageName, mICallback);
-                            }
-                        }
                     } else {
-                        boolean isStreamMute = mAudioService.isStreamMute(suggestedStream);
-                        if (direction == MediaSessionManager.DIRECTION_MUTE) {
-                            mAudioManager.setStreamMute(suggestedStream, !isStreamMute);
-                        } else {
-                            mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
-                                    flags, packageName);
-                            // Do not call setStreamMute when direction = 0 which is used just to
-                            // show the UI.
-                            if (isStreamMute && direction != 0) {
-                                mAudioManager.setStreamMute(suggestedStream, false);
-                            }
-                        }
+                        mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
+                                flags, packageName);
                     }
                 } catch (RemoteException e) {
                     Log.e(TAG, "Error adjusting default volume.", e);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 5d73149..1c9dfe0c 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,6 +26,7 @@
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.TypedValue;
+
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
@@ -83,11 +84,23 @@
     // Contains configurations settings that are different from the global configuration due to
     // stack specific operations. E.g. {@link #setBounds}.
     Configuration mOverrideConfig;
+    // True if the stack was forced to fullscreen disregarding the override configuration.
+    private boolean mForceFullscreen;
+    // The {@link #mBounds} before the stack was forced to fullscreen. Will be restored as the
+    // stack bounds once the stack is no longer forced to fullscreen.
+    final private Rect mPreForceFullscreenBounds;
+
+    // When true this stack is at the top of the screen and should be layed out to extend under
+    // the status bar.
+    boolean mUnderStatusBar;
 
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
         mOverrideConfig = Configuration.EMPTY;
+        mForceFullscreen = false;
+        mPreForceFullscreenBounds = new Rect();
+        mUnderStatusBar = true;
         // TODO: remove bounds from log, they are always 0.
         EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top,
                 mBounds.right, mBounds.bottom);
@@ -102,8 +115,6 @@
     }
 
     void resizeWindows() {
-        final boolean underStatusBar = mBounds.top == 0;
-
         final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
         for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
@@ -116,19 +127,29 @@
                                 "setBounds: Resizing " + win);
                         resizingWindows.add(win);
                     }
-                    win.mUnderStatusBar = underStatusBar;
                 }
             }
         }
     }
 
+    /** Set the stack bounds. Passing in null sets the bounds to fullscreen. */
     boolean setBounds(Rect bounds) {
         boolean oldFullscreen = mFullscreen;
         if (mDisplayContent != null) {
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
-            mFullscreen = mTmpRect.equals(bounds);
+            if (bounds == null) {
+                bounds = mTmpRect;
+                mFullscreen = true;
+            } else {
+                bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect
+                mFullscreen = mTmpRect.equals(bounds);
+            }
         }
 
+        if (bounds == null) {
+            // Can set to fullscreen if we don't have a display to get bounds from...
+            return false;
+        }
         if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) {
             return false;
         }
@@ -136,6 +157,7 @@
         mDimLayer.setBounds(bounds);
         mAnimationBackgroundSurface.setBounds(bounds);
         mBounds.set(bounds);
+        mUnderStatusBar = (mBounds.top == 0);
         updateOverrideConfiguration();
         return true;
     }
@@ -144,7 +166,7 @@
         out.set(mBounds);
     }
 
-    void updateOverrideConfiguration() {
+    private void updateOverrideConfiguration() {
         final Configuration serviceConfig = mService.mCurConfiguration;
         if (mFullscreen) {
             mOverrideConfig = Configuration.EMPTY;
@@ -176,6 +198,28 @@
         return mFullscreen;
     }
 
+    /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen.
+     * Returns true if something happened.
+     */
+    boolean forceFullscreen(boolean forceFullscreen) {
+        if (mForceFullscreen == forceFullscreen) {
+            return false;
+        }
+        mForceFullscreen = forceFullscreen;
+        if (forceFullscreen) {
+            if (mFullscreen) {
+                return false;
+            }
+            mPreForceFullscreenBounds.set(mBounds);
+            return setBounds(null);
+        } else {
+            if (!mFullscreen || mPreForceFullscreenBounds.isEmpty()) {
+                return false;
+            }
+            return setBounds(mPreForceFullscreenBounds);
+        }
+    }
+
     boolean isAnimating() {
         for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 3987132..0c5d06a 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -791,6 +791,7 @@
             } else if (dumpAll) {
                 pw.print(subPrefix); pw.println("no ScreenRotationAnimation ");
             }
+            pw.println();
         }
 
         pw.println();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 66bef41..8214026 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -284,12 +284,6 @@
     // The name of the boot animation service in init.rc.
     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
 
-    /** Minimum value for attachStack and resizeStack weight value */
-    public static final float STACK_WEIGHT_MIN = 0.2f;
-
-    /** Maximum value for attachStack and resizeStack weight value */
-    public static final float STACK_WEIGHT_MAX = 0.8f;
-
     static final int UPDATE_FOCUS_NORMAL = 0;
     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
     static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
@@ -5123,6 +5117,26 @@
         bounds.setEmpty();
     }
 
+    /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen.
+     * Returns a {@link Configuration} object that contains configurations settings
+     * that should be overridden due to the operation.
+     */
+    public Configuration forceStackToFullscreen(int stackId, boolean forceFullscreen) {
+        synchronized (mWindowMap) {
+            final TaskStack stack = mStackIdToStack.get(stackId);
+            if (stack == null) {
+                throw new IllegalArgumentException("resizeStack: stackId " + stackId
+                        + " not found.");
+            }
+            if (stack.forceFullscreen(forceFullscreen)) {
+                stack.resizeWindows();
+                stack.getDisplayContent().layoutNeeded = true;
+                performLayoutAndPlaceSurfacesLocked();
+            }
+            return new Configuration(stack.mOverrideConfig);
+        }
+    }
+
     // -------------------------------------------------------------
     // Misc IWindowSession methods
     // -------------------------------------------------------------
@@ -10513,15 +10527,13 @@
                 scheduleAnimationLocked();
             } else {
                 screenRotationAnimation.kill();
-                screenRotationAnimation = null;
-                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
+                mAnimator.setScreenRotationAnimationLocked(displayId, null);
                 updateRotation = true;
             }
         } else {
             if (screenRotationAnimation != null) {
                 screenRotationAnimation.kill();
-                screenRotationAnimation = null;
-                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
+                mAnimator.setScreenRotationAnimationLocked(displayId, null);
             }
             updateRotation = true;
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 98f00de..bb95305 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -342,10 +342,6 @@
     /** When true this window can be displayed on screens owther than mOwnerUid's */
     private boolean mShowToOwnerOnly;
 
-    /** When true this window is at the top of the screen and should be layed out to extend under
-     * the status bar */
-    boolean mUnderStatusBar = true;
-
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, final DisplayContent displayContent) {
@@ -509,8 +505,8 @@
 
         TaskStack stack = mAppToken != null ? getStack() : null;
         if (stack != null && !stack.isFullscreen()) {
-            getStackBounds(stack, mContainingFrame);
-            if (mUnderStatusBar) {
+            stack.getBounds(mContainingFrame);
+            if (stack.mUnderStatusBar) {
                 mContainingFrame.top = pf.top;
             }
         } else {
@@ -588,12 +584,13 @@
             y = mAttrs.y;
         }
 
+        // Make sure window fits in containing frame required by {@link Gravity#apply} call.
+        w = Math.min(w, pw);
+        h = Math.min(h, ph);
         Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
                 (int) (x + mAttrs.horizontalMargin * pw),
                 (int) (y + mAttrs.verticalMargin * ph), mFrame);
 
-        //System.out.println("Out: " + mFrame);
-
         // Now make sure the window fits in the overall display.
         Gravity.applyDisplay(mAttrs.gravity, df, mFrame);
 
@@ -808,10 +805,7 @@
     }
 
     void getStackBounds(Rect bounds) {
-        getStackBounds(getStack(), bounds);
-    }
-
-    private void getStackBounds(TaskStack stack, Rect bounds) {
+        final TaskStack stack = getStack();
         if (stack != null) {
             stack.getBounds(bounds);
             return;
@@ -1471,7 +1465,11 @@
     }
 
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+        final TaskStack stack = getStack();
         pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
+                if (stack != null) {
+                    pw.print(" stackId="); pw.print(stack.mStackId);
+                }
                 pw.print(" mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
         pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e4d0b77..b8f0d072 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1914,12 +1914,12 @@
         }
     }
 
-    public void setPasswordQuality(ComponentName who, int quality, int userHandle) {
+    public void setPasswordQuality(ComponentName who, int quality) {
         if (!mHasFeature) {
             return;
         }
+        final int userHandle = UserHandle.getCallingUserId();
         validateQualityConstant(quality);
-        enforceCrossUserPermission(userHandle);
 
         synchronized (this) {
             if (who == null) {
@@ -1963,11 +1963,11 @@
         }
     }
 
-    public void setPasswordMinimumLength(ComponentName who, int length, int userHandle) {
+    public void setPasswordMinimumLength(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2010,11 +2010,11 @@
         }
     }
 
-    public void setPasswordHistoryLength(ComponentName who, int length, int userHandle) {
+    public void setPasswordHistoryLength(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2057,11 +2057,11 @@
         }
     }
 
-    public void setPasswordExpirationTimeout(ComponentName who, long timeout, int userHandle) {
+    public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2226,11 +2226,11 @@
         }
     }
 
-    public void setPasswordMinimumUpperCase(ComponentName who, int length, int userHandle) {
+    public void setPasswordMinimumUpperCase(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2273,8 +2273,8 @@
         }
     }
 
-    public void setPasswordMinimumLowerCase(ComponentName who, int length, int userHandle) {
-        enforceCrossUserPermission(userHandle);
+    public void setPasswordMinimumLowerCase(ComponentName who, int length) {
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2317,11 +2317,11 @@
         }
     }
 
-    public void setPasswordMinimumLetters(ComponentName who, int length, int userHandle) {
+    public void setPasswordMinimumLetters(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2364,11 +2364,11 @@
         }
     }
 
-    public void setPasswordMinimumNumeric(ComponentName who, int length, int userHandle) {
+    public void setPasswordMinimumNumeric(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2411,11 +2411,11 @@
         }
     }
 
-    public void setPasswordMinimumSymbols(ComponentName who, int length, int userHandle) {
+    public void setPasswordMinimumSymbols(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2458,11 +2458,11 @@
         }
     }
 
-    public void setPasswordMinimumNonLetter(ComponentName who, int length, int userHandle) {
+    public void setPasswordMinimumNonLetter(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2522,8 +2522,7 @@
 
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
-            getActiveAdminForCallerLocked(null,
-                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+            getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
             if (policy.mActivePasswordQuality < getPasswordQuality(null, userHandle)
                     || policy.mActivePasswordLength < getPasswordMinimumLength(null, userHandle)) {
                 return false;
@@ -2556,11 +2555,11 @@
         }
     }
 
-    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, int userHandle) {
+    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2632,11 +2631,11 @@
         return strictestAdmin;
     }
 
-    public boolean resetPassword(String passwordOrNull, int flags, int userHandle) {
+    public boolean resetPassword(String passwordOrNull, int flags) {
         if (!mHasFeature) {
             return false;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         enforceNotManagedProfile(userHandle, "reset the password");
 
         String password = passwordOrNull != null ? passwordOrNull : "";
@@ -2767,11 +2766,11 @@
         return true;
     }
 
-    public void setMaximumTimeToLock(ComponentName who, long timeMs, int userHandle) {
+    public void setMaximumTimeToLock(ComponentName who, long timeMs) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3050,7 +3049,10 @@
             mHandler.post(new Runnable() {
                 public void run() {
                     try {
-                        ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
+                        IActivityManager am = ActivityManagerNative.getDefault();
+                        if (am.getCurrentUser().id == userHandle) {
+                            am.switchUser(UserHandle.USER_OWNER);
+                        }
                         if (!mUserManager.removeUser(userHandle)) {
                             Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
                         }
@@ -3231,11 +3233,10 @@
     }
 
     public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
-            String exclusionList, int userHandle) {
+            String exclusionList) {
         if (!mHasFeature) {
             return null;
         }
-        enforceCrossUserPermission(userHandle);
         synchronized(this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3261,7 +3262,7 @@
             // If the user is not the owner, don't set the global proxy. Fail silently.
             if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
                 Slog.w(LOG_TAG, "Only the owner is allowed to set the global proxy. User "
-                        + userHandle + " is not permitted.");
+                        + UserHandle.getCallingUserId() + " is not permitted.");
                 return null;
             }
             if (proxySpec == null) {
@@ -3371,11 +3372,11 @@
      * Set the storage encryption request for a single admin.  Returns the new total request
      * status (for all admins).
      */
-    public int setStorageEncryption(ComponentName who, boolean encrypt, int userHandle) {
+    public int setStorageEncryption(ComponentName who, boolean encrypt) {
         if (!mHasFeature) {
             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             // Check for permissions
             if (who == null) {
@@ -3507,11 +3508,11 @@
     /**
      * Set whether the screen capture is disabled for the user managed by the specified admin.
      */
-    public void setScreenCaptureDisabled(ComponentName who, int userHandle, boolean disabled) {
+    public void setScreenCaptureDisabled(ComponentName who, boolean disabled) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3566,11 +3567,11 @@
     /**
      * Set whether auto time is required by the specified admin (must be device owner).
      */
-    public void setAutoTimeRequired(ComponentName who, int userHandle, boolean required) {
+    public void setAutoTimeRequired(ComponentName who, boolean required) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3617,11 +3618,11 @@
     /**
      * Disables all device cameras according to the specified admin.
      */
-    public void setCameraDisabled(ComponentName who, boolean disabled, int userHandle) {
+    public void setCameraDisabled(ComponentName who, boolean disabled) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -3666,11 +3667,11 @@
     /**
      * Selectively disable keyguard features.
      */
-    public void setKeyguardDisabledFeatures(ComponentName who, int which, int userHandle) {
+    public void setKeyguardDisabledFeatures(ComponentName who, int which) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         enforceNotManagedProfile(userHandle, "disable keyguard features");
         synchronized (this) {
             if (who == null) {
@@ -3920,7 +3921,7 @@
         Bundle userRestrictions = mUserManager.getUserRestrictions();
         mUserManager.setUserRestrictions(new Bundle(), userHandle);
         if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) {
-            audioManager.setMasterMute(false);
+            audioManager.adjustMasterVolume(AudioManager.ADJUST_UNMUTE, 0);
         }
         if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) {
             audioManager.setMicrophoneMute(false);
@@ -4216,11 +4217,11 @@
     }
 
     public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
-            PersistableBundle args, int userHandle) {
+            PersistableBundle args) {
         if (!mHasFeature) {
             return;
         }
-        enforceCrossUserPermission(userHandle);
+        final int userHandle = UserHandle.getCallingUserId();
         enforceNotManagedProfile(userHandle, "set trust agent configuration");
         synchronized (this) {
             if (admin == null) {
@@ -4841,7 +4842,8 @@
                     if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
                         iAudioService.setMicrophoneMute(true, who.getPackageName());
                     } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        iAudioService.setMasterMute(true, 0, who.getPackageName(), null);
+                        iAudioService.adjustMasterVolume(AudioManager.ADJUST_MUTE, 0,
+                                who.getPackageName());
                     }
                 } catch (RemoteException re) {
                     Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
@@ -4906,7 +4908,8 @@
                     if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
                         iAudioService.setMicrophoneMute(false, who.getPackageName());
                     } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        iAudioService.setMasterMute(false, 0, who.getPackageName(), null);
+                        iAudioService.adjustMasterVolume(AudioManager.ADJUST_UNMUTE, 0,
+                                who.getPackageName());
                     }
                 } catch (RemoteException re) {
                     Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
@@ -5361,8 +5364,6 @@
 
     @Override
     public void setMasterVolumeMuted(ComponentName who, boolean on) {
-        final ContentResolver contentResolver = mContext.getContentResolver();
-
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -5372,7 +5373,9 @@
             IAudioService iAudioService = IAudioService.Stub.asInterface(
                     ServiceManager.getService(Context.AUDIO_SERVICE));
             try{
-                iAudioService.setMasterMute(on, 0, who.getPackageName(), null);
+                iAudioService.adjustMasterVolume(
+                        on ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE, 0,
+                        who.getPackageName());
             } catch (RemoteException re) {
                 Slog.e(LOG_TAG, "Failed to setMasterMute", re);
             }
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index b508c89..9d13d3c 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -24,6 +24,7 @@
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbInterface;
+import android.media.AudioService;
 import android.media.AudioSystem;
 import android.media.IAudioService;
 import android.midi.MidiDeviceInfo;
@@ -179,15 +180,16 @@
                         " alsaDevice: " + alsaDevice);
             return;
         }
-        String params = ("card=" + alsaCard + ";device=" + alsaDevice);
 
+        String address = AudioService.makeAlsaAddressString(alsaCard, alsaDevice);
         try {
             // Playback Device
             if (audioDevice.mHasPlayback) {
                 int device = (audioDevice == mAccessoryAudioDevice ?
                         AudioSystem.DEVICE_OUT_USB_ACCESSORY :
                         AudioSystem.DEVICE_OUT_USB_DEVICE);
-                mAudioService.setWiredDeviceConnectionState(device, state, params);
+                mAudioService.setWiredDeviceConnectionState(
+                        device, state, address, audioDevice.mDeviceName);
             }
 
             // Capture Device
@@ -195,7 +197,8 @@
                int device = (audioDevice == mAccessoryAudioDevice ?
                         AudioSystem.DEVICE_IN_USB_ACCESSORY :
                         AudioSystem.DEVICE_IN_USB_DEVICE);
-                mAudioService.setWiredDeviceConnectionState(device, state, params);
+                mAudioService.setWiredDeviceConnectionState(
+                        device, state, address, audioDevice.mDeviceName);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
diff --git a/services/usb/java/com/android/server/usb/UsbAudioDevice.java b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
index 069d917..bdd28e4 100644
--- a/services/usb/java/com/android/server/usb/UsbAudioDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
@@ -53,7 +53,6 @@
         sb.append("UsbAudioDevice: [card: " + mCard);
         sb.append(", device: " + mDevice);
         sb.append(", name: " + mDeviceName);
-        sb.append(", description: " + mDeviceDescription);
         sb.append(", hasPlayback: " + mHasPlayback);
         sb.append(", hasCapture: " + mHasCapture);
         sb.append(", class: 0x" + Integer.toHexString(mDeviceClass) + "]");
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index 1cf00d2..e489279 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -31,6 +31,8 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.util.Base64;
 import com.android.server.FgThread;
@@ -206,6 +208,12 @@
                     break;
 
                 case MESSAGE_ADB_CONFIRM: {
+                    if ("trigger_restart_min_framework".equals(
+                            SystemProperties.get("vold.decrypt"))) {
+                        Slog.d(TAG, "Deferring adb confirmation until after vold decrypt");
+                        sendResponse("NO");
+                        break;
+                    }
                     String key = (String)msg.obj;
                     String fingerprints = getFingerprints(key);
                     if ("".equals(fingerprints)) {
@@ -279,7 +287,7 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
             try {
-                mContext.startActivity(intent);
+                mContext.startActivityAsUser(intent, UserHandle.OWNER);
                 return true;
             } catch (ActivityNotFoundException e) {
                 Slog.e(TAG, "unable to start adb whitelist activity: " + componentName, e);
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index a180f44..108c0af 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -260,6 +260,7 @@
         /** @hide */
         public void onConferenceParticipantsChanged(Connection c,
                 List<ConferenceParticipant> participants) {}
+        public void onConferenceStarted() {}
     }
 
     /** @hide */
@@ -1001,14 +1002,11 @@
     /**
      * Informs listeners that this {@code Connection} has processed a character in the post-dial
      * started state. This is done when (a) the {@code Connection} is issuing a DTMF sequence;
-     * (b) it has encountered a "wait" character; and (c) it wishes to signal Telecom to play
-     * the corresponding DTMF tone locally.
+     * and (b) it wishes to signal Telecom to play the corresponding DTMF tone locally.
      *
      * @param nextChar The DTMF character that was just processed by the {@code Connection}.
-     *
-     * @hide
      */
-    public final void setNextPostDialWaitChar(char nextChar) {
+    public final void setNextPostDialChar(char nextChar) {
         checkImmutable();
         for (Listener l : mListeners) {
             l.onPostDialChar(this, nextChar);
@@ -1422,4 +1420,13 @@
             l.onConferenceParticipantsChanged(this, conferenceParticipants);
         }
     }
+
+    /**
+     * Notifies listeners that a conference call has been started.
+     */
+    protected void notifyConferenceStarted() {
+        for (Listener l : mListeners) {
+            l.onConferenceStarted();
+        }
+    }
 }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 052a481..a94c2f6 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -40,15 +40,13 @@
 /**
  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
  * want those calls to be integrated into the dialer and in-call UI should build an instance of
- * this class and register it with the system using {@link TelecomManager#registerPhoneAccount}.
+ * this class and register it with the system using {@link TelecomManager}.
  * <p>
  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
- * should supply a valid {@link PhoneAccountHandle} that references the {@link ConnectionService}
+ * should supply a valid {@link PhoneAccountHandle} that references the connection service
  * implementation Telecom will use to interact with the app.
- * @hide
  */
-@SystemApi
 public class PhoneAccount implements Parcelable {
 
     /**
@@ -62,7 +60,9 @@
      * if the user has explicitly selected it to be used as the default connection manager.
      * <p>
      * See {@link #getCapabilities}
+     * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
 
     /**
@@ -76,6 +76,7 @@
      * <p>
      * {@hide}
      */
+    @SystemApi
     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
 
     /**
@@ -94,6 +95,7 @@
      * See {@link #getCapabilities}
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
 
     /**
@@ -111,6 +113,7 @@
      * See {@link #getCapabilities}
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_MULTI_USER = 0x20;
 
     /**
@@ -203,6 +206,7 @@
         }
 
         /** @hide */
+        @SystemApi
         public Builder setAccountHandle(PhoneAccountHandle accountHandle) {
             mAccountHandle = accountHandle;
             return this;
@@ -333,6 +337,7 @@
          * @return The builder.
          * @hide
          */
+        @SystemApi
         public Builder addSupportedUriScheme(String uriScheme) {
             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
                 this.mSupportedUriSchemes.add(uriScheme);
@@ -423,6 +428,7 @@
      * @return The builder.
      * @hide
      */
+    @SystemApi
     public Builder toBuilder() { return new Builder(this); }
 
     /**
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 97af41a..570f5fd 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -29,16 +29,13 @@
  * The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two
  * parts:
  * <ul>
- *  <li>The component name of the associated {@link ConnectionService}.</li>
+ *  <li>The component name of the associated connection service.</li>
  *  <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same
  *      component name.</li>
  * </ul>
  *
- * See {@link PhoneAccount},
- * {@link TelecomManager#registerPhoneAccount TelecomManager.registerPhoneAccount}.
- * @hide
+ * See {@link PhoneAccount}, {@link TelecomManager}.
  */
-@SystemApi
 public class PhoneAccountHandle implements Parcelable {
     private final ComponentName mComponentName;
     private final String mId;
@@ -51,6 +48,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public PhoneAccountHandle(
             ComponentName componentName,
             String id,
@@ -61,8 +59,8 @@
     }
 
     /**
-     * The {@code ComponentName} of the {@link android.telecom.ConnectionService} which is
-     * responsible for making phone calls using this {@code PhoneAccountHandle}.
+     * The {@code ComponentName} of the connection service which is responsible for making phone
+     * calls using this {@code PhoneAccountHandle}.
      *
      * @return A suitable {@code ComponentName}.
      */
@@ -72,9 +70,9 @@
 
     /**
      * A string that uniquely distinguishes this particular {@code PhoneAccountHandle} from all the
-     * others supported by the {@link ConnectionService} that created it.
+     * others supported by the connection service that created it.
      * <p>
-     * A {@code ConnectionService} must select identifiers that are stable for the lifetime of
+     * A connection service must select identifiers that are stable for the lifetime of
      * their users' relationship with their service, across many Android devices. For example, a
      * good set of identifiers might be the email addresses with which with users registered for
      * their accounts with a particular service. Depending on how a service chooses to operate,
@@ -92,6 +90,7 @@
      * @return the {@link UserHandle} to use when connecting to this PhoneAccount.
      * @hide
      */
+    @SystemApi
     public UserHandle getUserHandle() {
         return mUserHandle;
     }
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 073dcd5f..a9b725b 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -60,11 +60,16 @@
                 mPendingConnections.remove(connection);
                 // Unconditionally initialize the connection ...
                 connection.setConnectionCapabilities(parcel.getConnectionCapabilities());
-                connection.setAddress(
-                        parcel.getHandle(), parcel.getHandlePresentation());
-                connection.setCallerDisplayName(
-                        parcel.getCallerDisplayName(),
-                        parcel.getCallerDisplayNamePresentation());
+                if (parcel.getHandle() != null
+                    || parcel.getState() != Connection.STATE_DISCONNECTED) {
+                    connection.setAddress(parcel.getHandle(), parcel.getHandlePresentation());
+                }
+                if (parcel.getCallerDisplayName() != null
+                    || parcel.getState() != Connection.STATE_DISCONNECTED) {
+                    connection.setCallerDisplayName(
+                            parcel.getCallerDisplayName(),
+                            parcel.getCallerDisplayNamePresentation());
+                }
                 // Set state after handle so that the client can identify the connection.
                 if (parcel.getState() == Connection.STATE_DISCONNECTED) {
                     connection.setDisconnected(parcel.getDisconnectCause());
@@ -235,8 +240,12 @@
 
         @Override
         public void setVideoProvider(String callId, IVideoProvider videoProvider) {
+            RemoteConnection.VideoProvider remoteVideoProvider = null;
+            if (videoProvider != null) {
+                remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider);
+            }
             findConnectionForAction(callId, "setVideoProvider")
-                    .setVideoProvider(new RemoteConnection.VideoProvider(videoProvider));
+                    .setVideoProvider(remoteVideoProvider);
         }
 
         @Override
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1a6b292..6c5f1c6 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -106,7 +106,6 @@
      * {@link VideoProfile.VideoState#BIDIRECTIONAL},
      * {@link VideoProfile.VideoState#RX_ENABLED},
      * {@link VideoProfile.VideoState#TX_ENABLED}.
-     * @hide
      */
     public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
             "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
@@ -117,9 +116,7 @@
      * {@link PhoneAccountHandle} to use when making the call.
      * <p class="note">
      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
             "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
 
@@ -139,10 +136,7 @@
      * {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle}
      * which contains metadata about the call. This {@link Bundle} will be saved into
      * {@code Call.Details}.
-     *
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_OUTGOING_CALL_EXTRAS =
             "android.telecom.extra.OUTGOING_CALL_EXTRAS";
 
@@ -554,9 +548,7 @@
      *
      * @param account The {@link PhoneAccountHandle}.
      * @return The {@link PhoneAccount} object.
-     * @hide
      */
-    @SystemApi
     public PhoneAccount getPhoneAccount(PhoneAccountHandle account) {
         try {
             if (isServiceConnected()) {
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index f5cb054..e62e994 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -21,8 +21,6 @@
 
 /**
  * Represents attributes of video calls.
- *
- * {@hide}
  */
 public class VideoProfile implements Parcelable {
     /**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index a59505c..69bb4bb 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -34,11 +34,9 @@
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
-import android.telephony.Rlog;
 import android.text.style.TtsSpan;
 import android.util.SparseIntArray;
 
-import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
@@ -1843,7 +1841,7 @@
         // to the list.
         number = extractNetworkPortionAlt(number);
 
-        Rlog.d(LOG_TAG, "subId:" + subId + ", number: " +  number + ", defaultCountryIso:" +
+        Rlog.d(LOG_TAG, "subId:" + subId + ", defaultCountryIso:" +
                 ((defaultCountryIso == null) ? "NULL" : defaultCountryIso));
 
         String emergencyNumbers = "";
@@ -2200,8 +2198,8 @@
         if (!TextUtils.isEmpty(dialStr)) {
             if (isReallyDialable(dialStr.charAt(0)) &&
                 isNonSeparator(dialStr)) {
-                String currIso = SystemProperties.get(PROPERTY_OPERATOR_ISO_COUNTRY, "");
-                String defaultIso = SystemProperties.get(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
+                String currIso = TelephonyManager.getDefault().getNetworkCountryIso();
+                String defaultIso = TelephonyManager.getDefault().getSimCountryIso();
                 if (!TextUtils.isEmpty(currIso) && !TextUtils.isEmpty(defaultIso)) {
                     return cdmaCheckAndProcessPlusCodeByNumberFormat(dialStr,
                             getFormatTypeFromCountryCode(currIso),
@@ -2223,7 +2221,7 @@
     public static String cdmaCheckAndProcessPlusCodeForSms(String dialStr) {
         if (!TextUtils.isEmpty(dialStr)) {
             if (isReallyDialable(dialStr.charAt(0)) && isNonSeparator(dialStr)) {
-                String defaultIso = SystemProperties.get(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
+                String defaultIso = TelephonyManager.getDefault().getSimCountryIso();
                 if (!TextUtils.isEmpty(defaultIso)) {
                     int format = getFormatTypeFromCountryCode(defaultIso);
                     return cdmaCheckAndProcessPlusCodeByNumberFormat(dialStr, format, format);
@@ -2339,15 +2337,13 @@
      *
      * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
      * @return A {@code CharSequence} with appropriate annotations.
-     *
-     * @hide
      */
-    public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
+    public static CharSequence getPhoneTtsSpannable(CharSequence phoneNumber) {
         if (phoneNumber == null) {
             return null;
         }
         Spannable spannable = Spannable.Factory.getInstance().newSpannable(phoneNumber);
-        PhoneNumberUtils.ttsSpanAsPhoneNumber(spannable, 0, spannable.length());
+        PhoneNumberUtils.addPhoneTtsSpan(spannable, 0, spannable.length());
         return spannable;
     }
 
@@ -2358,19 +2354,83 @@
      * @param s A {@code Spannable} to annotate.
      * @param start The starting character position of the phone number in {@code s}.
      * @param end The ending character position of the phone number in {@code s}.
-     *
-     * @hide
      */
-    public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
-        s.setSpan(
-                new TtsSpan.TelephoneBuilder()
-                        .setNumberParts(splitAtNonNumerics(s.subSequence(start, end)))
-                        .build(),
+    public static void addPhoneTtsSpan(Spannable s, int start, int end) {
+        s.setSpan(getPhoneTtsSpan(s.subSequence(start, end).toString()),
                 start,
                 end,
                 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
     }
 
+    /**
+     * Wrap the supplied {@code CharSequence} with a {@code TtsSpan}, annotating it as
+     * containing a phone number in its entirety.
+     *
+     * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
+     * @return A {@code CharSequence} with appropriate annotations.
+     * @deprecated Renamed {@link #getPhoneTtsSpannable}.
+     *
+     * @hide
+     */
+    @Deprecated
+    public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
+        return getPhoneTtsSpannable(phoneNumber);
+    }
+
+    /**
+     * Attach a {@link TtsSpan} to the supplied {@code Spannable} at the indicated location,
+     * annotating that location as containing a phone number.
+     *
+     * @param s A {@code Spannable} to annotate.
+     * @param start The starting character position of the phone number in {@code s}.
+     * @param end The ending character position of the phone number in {@code s}.
+     *
+     * @deprecated Renamed {@link #addPhoneTtsSpan}.
+     *
+     * @hide
+     */
+    @Deprecated
+    public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
+        addPhoneTtsSpan(s, start, end);
+    }
+
+    /**
+     * Create a {@code TtsSpan} for the supplied {@code String}.
+     *
+     * @param phoneNumberString A {@code String} the entirety of which represents a phone number.
+     * @return A {@code TtsSpan} for {@param phoneNumberString}.
+     */
+    public static TtsSpan getPhoneTtsSpan(String phoneNumberString) {
+        if (phoneNumberString == null) {
+            return null;
+        }
+
+        // Parse the phone number
+        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+        PhoneNumber phoneNumber = null;
+        try {
+            // Don't supply a defaultRegion so this fails for non-international numbers because
+            // we don't want to TalkBalk to read a country code (e.g. +1) if it is not already
+            // present
+            phoneNumber = phoneNumberUtil.parse(phoneNumberString, /* defaultRegion */ null);
+        } catch (NumberParseException ignored) {
+        }
+
+        // Build a telephone tts span
+        final TtsSpan.TelephoneBuilder builder = new TtsSpan.TelephoneBuilder();
+        if (phoneNumber == null) {
+            // Strip separators otherwise TalkBack will be silent
+            // (this behavior was observed with TalkBalk 4.0.2 from their alpha channel)
+            builder.setNumberParts(splitAtNonNumerics(phoneNumberString));
+        } else {
+            if (phoneNumber.hasCountryCode()) {
+                builder.setCountryCode(Integer.toString(phoneNumber.getCountryCode()));
+            }
+            builder.setNumberParts(Long.toString(phoneNumber.getNationalNumber()));
+        }
+        return builder.build();
+    }
+
     // Split a phone number like "+20(123)-456#" using spaces, ignoring anything that is not
     // a digit, to produce a result like "20 123 456".
     private static String splitAtNonNumerics(CharSequence number) {
@@ -2388,11 +2448,11 @@
 
     private static String getCurrentIdp(boolean useNanp) {
         String ps = null;
-        if(useNanp)
+        if (useNanp) {
             ps = NANP_IDP_STRING;
-        else{
+        } else {
             // in case, there is no IDD is found, we shouldn't convert it.
-            ps = SystemProperties.get(PROPERTY_OPERATOR_IDP_STRING, PLUS_SIGN_STRING);                
+            ps = SystemProperties.get(PROPERTY_OPERATOR_IDP_STRING, PLUS_SIGN_STRING);
         }
         return ps;
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c67629d..aca94e9 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1101,9 +1101,7 @@
             // What else can we do?
             return false;
         }
-        // FIXME: use better way to get roaming status instead of reading from system property
-        return Boolean.parseBoolean(TelephonyManager.getTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null));
+        return TelephonyManager.getDefault().isNetworkRoaming(subId);
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 339fc6d..ba5a679 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1077,7 +1077,7 @@
      * on a CDMA network).
      */
     public String getNetworkOperator() {
-        return getNetworkOperator(getDefaultSubscription());
+        return getNetworkOperatorForPhone(getDefaultPhone());
     }
 
     /**
@@ -1091,8 +1091,23 @@
      * @param subId
      */
     /** {@hide} */
-   public String getNetworkOperator(int subId) {
+   public String getNetworkOperatorForSubscription(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
+        return getNetworkOperatorForPhone(phoneId);
+     }
+
+    /**
+     * Returns the numeric name (MCC+MNC) of current registered operator
+     * for a particular subscription.
+     * <p>
+     * Availability: Only when user is registered to a network. Result may be
+     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
+     * on a CDMA network).
+     *
+     * @param phoneId
+     * @hide
+     **/
+   public String getNetworkOperatorForPhone(int phoneId) {
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
      }
 
@@ -1130,7 +1145,7 @@
      * on a CDMA network).
      */
     public String getNetworkCountryIso() {
-        return getNetworkCountryIso(getDefaultSubscription());
+        return getNetworkCountryIsoForPhone(getDefaultPhone());
     }
 
     /**
@@ -1144,8 +1159,23 @@
      * @param subId for which Network CountryIso is returned
      */
     /** {@hide} */
-    public String getNetworkCountryIso(int subId) {
+    public String getNetworkCountryIsoForSubscription(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
+        return getNetworkCountryIsoForPhone(phoneId);
+    }
+
+    /**
+     * Returns the ISO country code equivalent of the current registered
+     * operator's MCC (Mobile Country Code) of a subscription.
+     * <p>
+     * Availability: Only when user is registered to a network. Result may be
+     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
+     * on a CDMA network).
+     *
+     * @param phoneId for which Network CountryIso is returned
+     */
+    /** {@hide} */
+    public String getNetworkCountryIsoForPhone(int phoneId) {
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
     }
 
@@ -1537,6 +1567,34 @@
      * @see #getSimState
      */
     public String getSimOperator() {
+        return getSimOperatorNumeric();
+    }
+
+    /**
+     * Returns the MCC+MNC (mobile country code + mobile network code) of the
+     * provider of the SIM. 5 or 6 decimal digits.
+     * <p>
+     * Availability: SIM state must be {@link #SIM_STATE_READY}
+     *
+     * @see #getSimState
+     *
+     * @param subId for which SimOperator is returned
+     * @hide
+     */
+    public String getSimOperator(int subId) {
+        return getSimOperatorNumericForSubscription(subId);
+    }
+
+    /**
+     * Returns the MCC+MNC (mobile country code + mobile network code) of the
+     * provider of the SIM. 5 or 6 decimal digits.
+     * <p>
+     * Availability: SIM state must be {@link #SIM_STATE_READY}
+     *
+     * @see #getSimState
+     * @hide
+     */
+    public String getSimOperatorNumeric() {
         int subId = SubscriptionManager.getDefaultDataSubId();
         if (!SubscriptionManager.isUsableSubIdValue(subId)) {
             subId = SubscriptionManager.getDefaultSmsSubId();
@@ -1547,8 +1605,8 @@
                 }
             }
         }
-        Rlog.d(TAG, "getSimOperator(): default subId=" + subId);
-        return getSimOperator(subId);
+        Rlog.d(TAG, "getSimOperatorNumeric(): default subId=" + subId);
+        return getSimOperatorNumericForSubscription(subId);
     }
 
     /**
@@ -1560,14 +1618,24 @@
      * @see #getSimState
      *
      * @param subId for which SimOperator is returned
+     * @hide
      */
-    /** {@hide} */
-    public String getSimOperator(int subId) {
+    public String getSimOperatorNumericForSubscription(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
-        String operator = getTelephonyProperty(phoneId,
+        return getSimOperatorNumericForPhone(phoneId);
+    }
+
+   /**
+     * Returns the MCC+MNC (mobile country code + mobile network code) of the
+     * provider of the SIM for a particular subscription. 5 or 6 decimal digits.
+     * <p>
+     *
+     * @param phoneId for which SimOperator is returned
+     * @hide
+     */
+    public String getSimOperatorNumericForPhone(int phoneId) {
+        return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
-        Rlog.d(TAG, "getSimOperator: subId=" + subId + " operator=" + operator);
-        return operator;
     }
 
     /**
@@ -1578,7 +1646,7 @@
      * @see #getSimState
      */
     public String getSimOperatorName() {
-        return getSimOperatorName(getDefaultSubscription());
+        return getSimOperatorNameForPhone(getDefaultPhone());
     }
 
     /**
@@ -1589,30 +1657,61 @@
      * @see #getSimState
      *
      * @param subId for which SimOperatorName is returned
+     * @hide
      */
-    /** {@hide} */
-    public String getSimOperatorName(int subId) {
+    public String getSimOperatorNameForSubscription(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
-        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");
+        return getSimOperatorNameForPhone(phoneId);
+    }
+
+    /**
+     * Returns the Service Provider Name (SPN).
+     *
+     * @hide
+     */
+    public String getSimOperatorNameForPhone(int phoneId) {
+         return getTelephonyProperty(phoneId,
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");
     }
 
     /**
      * Returns the ISO country code equivalent for the SIM provider's country code.
      */
     public String getSimCountryIso() {
-        return getSimCountryIso(getDefaultSubscription());
+        return getSimCountryIsoForPhone(getDefaultPhone());
     }
 
     /**
      * Returns the ISO country code equivalent for the SIM provider's country code.
      *
      * @param subId for which SimCountryIso is returned
+     *
+     * @hide
      */
-    /** {@hide} */
     public String getSimCountryIso(int subId) {
+        return getSimCountryIsoForSubscription(subId);
+    }
+
+    /**
+     * Returns the ISO country code equivalent for the SIM provider's country code.
+     *
+     * @param subId for which SimCountryIso is returned
+     *
+     * @hide
+     */
+    public String getSimCountryIsoForSubscription(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
-        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
-                "");
+        return getSimCountryIsoForPhone(phoneId);
+    }
+
+    /**
+     * Returns the ISO country code equivalent for the SIM provider's country code.
+     *
+     * @hide
+     */
+    public String getSimCountryIsoForPhone(int phoneId) {
+        return getTelephonyProperty(phoneId,
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
     }
 
     /**
@@ -3677,4 +3776,344 @@
            return false;
        }
    }
+
+   /**
+    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
+    *
+    * @hide
+    */
+    public void setSimOperatorNumeric(String numeric) {
+        int phoneId = getDefaultPhone();
+        setSimOperatorNumericForPhone(phoneId, numeric);
+    }
+
+   /**
+    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the given phone.
+    *
+    * @hide
+    */
+    public void setSimOperatorNumericForPhone(int phoneId, String numeric) {
+        setTelephonyProperty(phoneId,
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, numeric);
+    }
+
+    /**
+     * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
+     *
+     * @hide
+     */
+    public void setSimOperatorName(String name) {
+        int phoneId = getDefaultPhone();
+        setSimOperatorNameForPhone(phoneId, name);
+    }
+
+    /**
+     * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the given phone.
+     *
+     * @hide
+     */
+    public void setSimOperatorNameForPhone(int phoneId, String name) {
+        setTelephonyProperty(phoneId,
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, name);
+    }
+
+   /**
+    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY for the default phone.
+    *
+    * @hide
+    */
+    public void setSimCountryIso(String iso) {
+        int phoneId = getDefaultPhone();
+        setSimCountryIsoForPhone(phoneId, iso);
+    }
+
+   /**
+    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY for the given phone.
+    *
+    * @hide
+    */
+    public void setSimCountryIsoForPhone(int phoneId, String iso) {
+        setTelephonyProperty(phoneId,
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
+    }
+
+    /**
+     * Set TelephonyProperties.PROPERTY_SIM_STATE for the default phone.
+     *
+     * @hide
+     */
+    public void setSimState(String state) {
+        int phoneId = getDefaultPhone();
+        setSimStateForPhone(phoneId, state);
+    }
+
+    /**
+     * Set TelephonyProperties.PROPERTY_SIM_STATE for the given phone.
+     *
+     * @hide
+     */
+    public void setSimStateForPhone(int phoneId, String state) {
+        setTelephonyProperty(phoneId,
+                TelephonyProperties.PROPERTY_SIM_STATE, state);
+    }
+
+    /**
+     * Set baseband version for the default phone.
+     *
+     * @param version baseband version
+     * @hide
+     */
+    public void setBasebandVersion(String version) {
+        int phoneId = getDefaultPhone();
+        setBasebandVersionForPhone(phoneId, version);
+    }
+
+    /**
+     * Set baseband version by phone id.
+     *
+     * @param phoneId for which baseband version is set
+     * @param version baseband version
+     * @hide
+     */
+    public void setBasebandVersionForPhone(int phoneId, String version) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            String prop = TelephonyProperties.PROPERTY_BASEBAND_VERSION +
+                    ((phoneId == 0) ? "" : Integer.toString(phoneId));
+            SystemProperties.set(prop, version);
+        }
+    }
+
+    /**
+     * Set phone type for the default phone.
+     *
+     * @param type phone type
+     *
+     * @hide
+     */
+    public void setPhoneType(int type) {
+        int phoneId = getDefaultPhone();
+        setPhoneType(phoneId, type);
+    }
+
+    /**
+     * Set phone type by phone id.
+     *
+     * @param phoneId for which phone type is set
+     * @param type phone type
+     *
+     * @hide
+     */
+    public void setPhoneType(int phoneId, int type) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            TelephonyManager.setTelephonyProperty(phoneId,
+                    TelephonyProperties.CURRENT_ACTIVE_PHONE, String.valueOf(type));
+        }
+    }
+
+    /**
+     * Get OTASP number schema for the default phone.
+     *
+     * @param defaultValue default value
+     * @return OTA SP number schema
+     *
+     * @hide
+     */
+    public String getOtaSpNumberSchema(String defaultValue) {
+        int phoneId = getDefaultPhone();
+        return getOtaSpNumberSchemaForPhone(phoneId, defaultValue);
+    }
+
+    /**
+     * Get OTASP number schema by phone id.
+     *
+     * @param phoneId for which OTA SP number schema is get
+     * @param defaultValue default value
+     * @return OTA SP number schema
+     *
+     * @hide
+     */
+    public String getOtaSpNumberSchemaForPhone(int phoneId, String defaultValue) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            return TelephonyManager.getTelephonyProperty(phoneId,
+                    TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA, defaultValue);
+        }
+
+        return defaultValue;
+    }
+
+    /**
+     * Get SMS receive capable from system property for the default phone.
+     *
+     * @param defaultValue default value
+     * @return SMS receive capable
+     *
+     * @hide
+     */
+    public boolean getSmsReceiveCapable(boolean defaultValue) {
+        int phoneId = getDefaultPhone();
+        return getSmsReceiveCapableForPhone(phoneId, defaultValue);
+    }
+
+    /**
+     * Get SMS receive capable from system property by phone id.
+     *
+     * @param phoneId for which SMS receive capable is get
+     * @param defaultValue default value
+     * @return SMS receive capable
+     *
+     * @hide
+     */
+    public boolean getSmsReceiveCapableForPhone(int phoneId, boolean defaultValue) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            return Boolean.valueOf(TelephonyManager.getTelephonyProperty(phoneId,
+                    TelephonyProperties.PROPERTY_SMS_RECEIVE, String.valueOf(defaultValue)));
+        }
+
+        return defaultValue;
+    }
+
+    /**
+     * Get SMS send capable from system property for the default phone.
+     *
+     * @param defaultValue default value
+     * @return SMS send capable
+     *
+     * @hide
+     */
+    public boolean getSmsSendCapable(boolean defaultValue) {
+        int phoneId = getDefaultPhone();
+        return getSmsSendCapableForPhone(phoneId, defaultValue);
+    }
+
+    /**
+     * Get SMS send capable from system property by phone id.
+     *
+     * @param phoneId for which SMS send capable is get
+     * @param defaultValue default value
+     * @return SMS send capable
+     *
+     * @hide
+     */
+    public boolean getSmsSendCapableForPhone(int phoneId, boolean defaultValue) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            return Boolean.valueOf(TelephonyManager.getTelephonyProperty(phoneId,
+                    TelephonyProperties.PROPERTY_SMS_SEND, String.valueOf(defaultValue)));
+        }
+
+        return defaultValue;
+    }
+
+    /**
+     * Set the alphabetic name of current registered operator.
+     * @param name the alphabetic name of current registered operator.
+     * @hide
+     */
+    public void setNetworkOperatorName(String name) {
+        int phoneId = getDefaultPhone();
+        setNetworkOperatorNameForPhone(phoneId, name);
+    }
+
+    /**
+     * Set the alphabetic name of current registered operator.
+     * @param phoneId which phone you want to set
+     * @param name the alphabetic name of current registered operator.
+     * @hide
+     */
+    public void setNetworkOperatorNameForPhone(int phoneId, String name) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, name);
+        }
+    }
+
+    /**
+     * Set the numeric name (MCC+MNC) of current registered operator.
+     * @param operator the numeric name (MCC+MNC) of current registered operator
+     * @hide
+     */
+    public void setNetworkOperatorNumeric(String numeric) {
+        int phoneId = getDefaultPhone();
+        setNetworkOperatorNumericForPhone(phoneId, numeric);
+    }
+
+    /**
+     * Set the numeric name (MCC+MNC) of current registered operator.
+     * @param phoneId for which phone type is set
+     * @param operator the numeric name (MCC+MNC) of current registered operator
+     * @hide
+     */
+    public void setNetworkOperatorNumericForPhone(int phoneId, String numeric) {
+        setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, numeric);
+    }
+
+    /**
+     * Set roaming state of the current network, for GSM purposes.
+     * @param isRoaming is network in romaing state or not
+     * @hide
+     */
+    public void setNetworkRoaming(boolean isRoaming) {
+        int phoneId = getDefaultPhone();
+        setNetworkRoamingForPhone(phoneId, isRoaming);
+    }
+
+    /**
+     * Set roaming state of the current network, for GSM purposes.
+     * @param phoneId which phone you want to set
+     * @param isRoaming is network in romaing state or not
+     * @hide
+     */
+    public void setNetworkRoamingForPhone(int phoneId, boolean isRoaming) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
+                    isRoaming ? "true" : "false");
+        }
+    }
+
+    /**
+     * Set the ISO country code equivalent of the current registered
+     * operator's MCC (Mobile Country Code).
+     * @param iso the ISO country code equivalent of the current registered
+     * @hide
+     */
+    public void setNetworkCountryIso(String iso) {
+        int phoneId = getDefaultPhone();
+        setNetworkCountryIsoForPhone(phoneId, iso);
+    }
+
+    /**
+     * Set the ISO country code equivalent of the current registered
+     * operator's MCC (Mobile Country Code).
+     * @param phoneId which phone you want to set
+     * @param iso the ISO country code equivalent of the current registered
+     * @hide
+     */
+    public void setNetworkCountryIsoForPhone(int phoneId, String iso) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            setTelephonyProperty(phoneId,
+                    TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso);
+        }
+    }
+
+    /**
+     * Set the network type currently in use on the device for data transmission.
+     * @param type the network type currently in use on the device for data transmission
+     * @hide
+     */
+    public void setDataNetworkType(int type) {
+        int phoneId = getDefaultPhone();
+        setDataNetworkTypeForPhone(phoneId, type);
+    }
+
+    /**
+     * Set the network type currently in use on the device for data transmission.
+     * @param phoneId which phone you want to set
+     * @param type the network type currently in use on the device for data transmission
+     * @hide
+     */
+    public void setDataNetworkTypeForPhone(int phoneId, int type) {
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            setTelephonyProperty(phoneId,
+                    TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
+                    ServiceState.rilRadioTechnologyToString(type));
+        }
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 6fdf121..70ac268 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -453,10 +453,6 @@
      */
     void setPremiumSmsPermission(String packageName, int permission);
 
-    /**
-     * Set the SMS send permission for the specified package.
-     * Requires system permission.
-     */
      /**
      * Set the SMS send permission for the specified package.
      * Requires system permission.
@@ -483,6 +479,14 @@
      */
     boolean isImsSmsSupportedForSubscriber(int subId);
 
+    /**
+     * User needs to pick SIM for SMS if multiple SIMs present and if current subId passed in is not
+     * active/valid.
+     * @param subId current subId for sending SMS
+     * @return true if SIM for SMS sending needs to be chosen
+     */
+    boolean isSmsSimPickActivityNeeded(int subId);
+
     /*
      * get user prefered SMS subId
      * @return subId id
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index a2bd6d7..18036927 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -614,15 +614,27 @@
 
             int pos = value.indexOf('/');
             String idName = value.substring(pos + 1);
+            boolean create = value.startsWith("@+");
+            boolean isFrameworkId =
+                    mPlatformFile || value.startsWith("@android") || value.startsWith("@+android");
 
-            // if this is a framework id
-            if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
-                // look for idName in the android R classes
-                return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue);
+            // Look for the idName in project or android R class depending on isPlatform.
+            if (create) {
+                Integer idValue;
+                if (isFrameworkId) {
+                    idValue = Bridge.getResourceId(ResourceType.ID, idName);
+                } else {
+                    idValue = mContext.getProjectCallback().getResourceId(ResourceType.ID, idName);
+                }
+                return idValue == null ? defValue : idValue;
             }
-
-            // look for idName in the project R class.
-            return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue);
+            // This calls the same method as in if(create), but doesn't create a dynamic id, if
+            // one is not found.
+            if (isFrameworkId) {
+                return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue);
+            } else {
+                return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue);
+            }
         }
 
         // not a direct id valid reference? resolve it
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 3953624..3441878 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -289,6 +289,11 @@
             value = mRenderResources.resolveResValue(value);
         }
 
+        if (value == null) {
+            // unable to find the attribute.
+            return false;
+        }
+
         // check if this is a style resource
         if (value instanceof StyleResourceValue) {
             // get the id that will represent this style.
@@ -296,7 +301,6 @@
             return true;
         }
 
-
         int a;
         // if this is a framework value.
         if (value.isFramework()) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
new file mode 100644
index 0000000..e5023b8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.ResourceType;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Assumes that the AppCompat library is present in the project's classpath and creates an
+ * actionbar around it.
+ */
+public class AppCompatActionBar extends BridgeActionBar {
+
+    private Object mWindowDecorActionBar;
+    private static final String WINDOW_ACTION_BAR_CLASS = "android.support.v7.internal.app.WindowDecorActionBar";
+    private Class<?> mWindowActionBarClass;
+
+    /**
+     * Inflate the action bar and attach it to {@code parentView}
+     */
+    public AppCompatActionBar(@NonNull BridgeContext context, @NonNull SessionParams params,
+            @NonNull ViewGroup parentView) {
+        super(context, params, parentView);
+        int contentRootId = context.getProjectResourceValue(ResourceType.ID,
+                "action_bar_activity_content", 0);
+        View contentView = getDecorContent().findViewById(contentRootId);
+        if (contentView != null) {
+            assert contentView instanceof FrameLayout;
+            setContentRoot(((FrameLayout) contentView));
+        } else {
+            // Something went wrong. Create a new FrameLayout in the enclosing layout.
+            FrameLayout contentRoot = new FrameLayout(context);
+            setMatchParent(contentRoot);
+            mEnclosingLayout.addView(contentRoot);
+            setContentRoot(contentRoot);
+        }
+        try {
+            Class[] constructorParams = {View.class};
+            Object[] constructorArgs = {getDecorContent()};
+            mWindowDecorActionBar = params.getProjectCallback().loadView(WINDOW_ACTION_BAR_CLASS,
+                    constructorParams, constructorArgs);
+
+            mWindowActionBarClass = mWindowDecorActionBar == null ? null :
+                    mWindowDecorActionBar.getClass();
+            setupActionBar();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    protected ResourceValue getLayoutResource(BridgeContext context) {
+        // We always assume that the app has requested the action bar.
+        return context.getRenderResources().getProjectResource(ResourceType.LAYOUT,
+                "abc_screen_toolbar");
+    }
+
+    @Override
+    protected void setTitle(CharSequence title) {
+        if (title != null && mWindowDecorActionBar != null) {
+            Method setTitle = getMethod(mWindowActionBarClass, "setTitle", CharSequence.class);
+            invoke(setTitle, mWindowDecorActionBar, title);
+        }
+    }
+
+    @Override
+    protected void setSubtitle(CharSequence subtitle) {
+        if (subtitle != null && mWindowDecorActionBar != null) {
+            Method setSubtitle = getMethod(mWindowActionBarClass, "setSubtitle", CharSequence.class);
+            invoke(setSubtitle, mWindowDecorActionBar, subtitle);
+        }
+    }
+
+    @Override
+    protected void setIcon(String icon) {
+        // Do this only if the action bar doesn't already have an icon.
+        if (icon != null && !icon.isEmpty() && mWindowDecorActionBar != null) {
+            if (((Boolean) invoke(getMethod(mWindowActionBarClass, "hasIcon"), mWindowDecorActionBar)
+            )) {
+                Drawable iconDrawable = getDrawable(icon, false);
+                if (iconDrawable != null) {
+                    Method setIcon = getMethod(mWindowActionBarClass, "setIcon", Drawable.class);
+                    invoke(setIcon, mWindowDecorActionBar, iconDrawable);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void setHomeAsUp(boolean homeAsUp) {
+        if (mWindowDecorActionBar != null) {
+            Method setHomeAsUp = getMethod(mWindowActionBarClass,
+                    "setDefaultDisplayHomeAsUpEnabled", boolean.class);
+            invoke(setHomeAsUp, mWindowDecorActionBar, homeAsUp);
+        }
+    }
+
+    @Override
+    public void createMenuPopup() {
+        // it's hard to addd menus to appcompat's actionbar, since it'll use a lot of reflection.
+        // so we skip it for now.
+    }
+
+    @Nullable
+    private static Method getMethod(Class<?> owner, String name, Class<?>... parameterTypes) {
+        try {
+            return owner == null ? null : owner.getMethod(name, parameterTypes);
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Nullable
+    private static Object invoke(Method method, Object owner, Object... args) {
+        try {
+            return method == null ? null : method.invoke(owner, args);
+        } catch (InvocationTargetException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    // TODO: this is duplicated from FrameworkActionBarWrapper$WindowActionBarWrapper
+    @Nullable
+    private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+        RenderResources res = mBridgeContext.getRenderResources();
+        ResourceValue value = res.findResValue(name, isFramework);
+        value = res.resolveResValue(value);
+        if (value != null) {
+            return ResourceHelper.getDrawable(value, mBridgeContext);
+        }
+        return null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java
new file mode 100644
index 0000000..b29d25f
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.layoutlib.bridge.android.BridgeContext;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+
+/**
+ * An abstraction over two implementations of the ActionBar - framework and appcompat.
+ */
+public abstract class BridgeActionBar {
+    // Store a reference to the context so that we don't have to cast it repeatedly.
+    @NonNull protected final BridgeContext mBridgeContext;
+    @NonNull protected final SessionParams mParams;
+    // A Layout that contains the inflated action bar. The menu popup is added to this layout.
+    @NonNull protected final ViewGroup mEnclosingLayout;
+
+    private final View mDecorContent;
+    private final ActionBarCallback mCallback;
+
+    @NonNull private FrameLayout mContentRoot;
+
+    public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params,
+            @NonNull ViewGroup parentView) {
+        mBridgeContext = context;
+        mParams = params;
+        mCallback = params.getProjectCallback().getActionBarCallback();
+        ResourceValue layoutName = getLayoutResource(context);
+        if (layoutName == null) {
+            throw new RuntimeException("Unable to find the layout for Action Bar.");
+        }
+        int layoutId;
+        if (layoutName.isFramework()) {
+            layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
+                    layoutName.getName(), 0);
+        } else {
+            layoutId = context.getProjectResourceValue(layoutName.getResourceType(),
+                    layoutName.getName(), 0);
+
+        }
+        if (layoutId == 0) {
+            throw new RuntimeException(
+                    String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"",
+                            layoutName.getName(), layoutName.getResourceType()));
+        }
+        if (mCallback.isOverflowPopupNeeded()) {
+            // Create a RelativeLayout around the action bar, to which the overflow popup may be
+            // added.
+            mEnclosingLayout = new RelativeLayout(mBridgeContext);
+            setMatchParent(mEnclosingLayout);
+            parentView.addView(mEnclosingLayout);
+        } else {
+            mEnclosingLayout = parentView;
+        }
+
+        // Inflate action bar layout.
+        mDecorContent = LayoutInflater.from(context).inflate(layoutId, mEnclosingLayout, true);
+
+    }
+
+    /**
+     * Returns the Layout Resource that should be used to inflate the action bar. This layout
+     * should cover the complete screen, and have a FrameLayout included, where the content will
+     * be inflated.
+     */
+    protected abstract ResourceValue getLayoutResource(BridgeContext context);
+
+    protected void setContentRoot(FrameLayout contentRoot) {
+        mContentRoot = contentRoot;
+    }
+
+    @NonNull
+    public FrameLayout getContentRoot() {
+        return mContentRoot;
+    }
+
+    /**
+     * Returns the view inflated. This should contain both the ActionBar and the app content in it.
+     */
+    protected View getDecorContent() {
+        return mDecorContent;
+    }
+
+    /** Setup things like the title, subtitle, icon etc. */
+    protected void setupActionBar() {
+        setTitle();
+        setSutTitle();
+        setIcon();
+        setHomeAsUp(mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP);
+    }
+
+    protected abstract void setTitle(CharSequence title);
+    protected abstract void setSubtitle(CharSequence subtitle);
+    protected abstract void setIcon(String icon);
+    protected abstract void setHomeAsUp(boolean homeAsUp);
+
+    private void setTitle() {
+        RenderResources res = mBridgeContext.getRenderResources();
+
+        String title = mParams.getAppLabel();
+        ResourceValue titleValue = res.findResValue(title, false);
+        if (titleValue != null && titleValue.getValue() != null) {
+            setTitle(titleValue.getValue());
+        } else {
+            setTitle(title);
+        }
+    }
+
+    private void setSutTitle() {
+        String subTitle = mCallback.getSubTitle();
+        if (subTitle != null) {
+            setSubtitle(subTitle);
+        }
+    }
+
+    private void setIcon() {
+        String appIcon = mParams.getAppIcon();
+        if (appIcon != null) {
+            setIcon(appIcon);
+        }
+    }
+
+    public abstract void createMenuPopup();
+
+    public ActionBarCallback getCallBack() {
+        return mCallback;
+    }
+
+    protected static void setMatchParent(View view) {
+        view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java
similarity index 76%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java
index 2ff8d37..a1c9065 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java
@@ -31,7 +31,7 @@
 import android.content.res.TypedArray;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
-import android.view.LayoutInflater;
+import android.view.InflateException;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
@@ -44,70 +44,30 @@
 
 import java.util.ArrayList;
 
-public class ActionBarLayout {
+/**
+ * Creates the ActionBar as done by the framework.
+ */
+public class FrameworkActionBar extends BridgeActionBar {
 
     private static final String LAYOUT_ATTR_NAME = "windowActionBarFullscreenDecorLayout";
 
     // The Action Bar
-    @NonNull
-    private CustomActionBarWrapper mActionBar;
-
-    // Store another reference to the context so that we don't have to cast it repeatedly.
-    @NonNull
-    private final BridgeContext mBridgeContext;
-
-    @NonNull
-    private FrameLayout mContentRoot;
+    @NonNull private FrameworkActionBarWrapper mActionBar;
 
     // A fake parent for measuring views.
-    @Nullable
-    private ViewGroup mMeasureParent;
-
-    // A Layout that contains the inflated action bar. The menu popup is added to this layout.
-    @NonNull
-    private final RelativeLayout mEnclosingLayout;
+    @Nullable private ViewGroup mMeasureParent;
 
     /**
      * Inflate the action bar and attach it to {@code parentView}
      */
-    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params,
+    public FrameworkActionBar(@NonNull BridgeContext context, @NonNull SessionParams params,
             @NonNull ViewGroup parentView) {
+        super(context, params, parentView);
 
-        mBridgeContext = context;
+        View decorContent = getDecorContent();
 
-        ResourceValue layoutName = context.getRenderResources()
-                .findItemInTheme(LAYOUT_ATTR_NAME, true);
-        if (layoutName != null) {
-            // We may need to resolve the reference obtained.
-            layoutName = context.getRenderResources().findResValue(layoutName.getValue(),
-                    layoutName.isFramework());
-        }
-        int layoutId = 0;
-        String error = null;
-        if (layoutName == null) {
-            error = "Unable to find action bar layout (" + LAYOUT_ATTR_NAME
-                    + ") in the current theme.";
-        } else {
-            layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
-                    layoutName.getName(), 0);
-            if (layoutId == 0) {
-                error = String.format("Unable to resolve attribute \"%s\" of type \"%s\"",
-                        layoutName.getName(), layoutName.getResourceType());
-            }
-        }
-        if (layoutId == 0) {
-            throw new RuntimeException(error);
-        }
-        // Create a RelativeLayout to hold the action bar. The layout is needed so that we may
-        // add the menu popup to it.
-        mEnclosingLayout = new RelativeLayout(mBridgeContext);
-        setMatchParent(mEnclosingLayout);
-        parentView.addView(mEnclosingLayout);
-
-        // Inflate action bar layout.
-        View decorContent = LayoutInflater.from(context).inflate(layoutId, mEnclosingLayout, true);
-
-        mActionBar = CustomActionBarWrapper.getActionBarWrapper(context, params, decorContent);
+        mActionBar = FrameworkActionBarWrapper.getActionBarWrapper(context, getCallBack(),
+                decorContent);
 
         FrameLayout contentRoot = (FrameLayout) mEnclosingLayout.findViewById(android.R.id.content);
 
@@ -117,27 +77,62 @@
             contentRoot = new FrameLayout(context);
             setMatchParent(contentRoot);
             mEnclosingLayout.addView(contentRoot);
-            mContentRoot = contentRoot;
+            setContentRoot(contentRoot);
         } else {
-            mContentRoot = contentRoot;
-            mActionBar.setupActionBar();
+            setContentRoot(contentRoot);
+            setupActionBar();
             mActionBar.inflateMenus();
         }
     }
 
-    private void setMatchParent(View view) {
-        view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT));
+    @Override
+    protected ResourceValue getLayoutResource(BridgeContext context) {
+        ResourceValue layoutName =
+                context.getRenderResources().findItemInTheme(LAYOUT_ATTR_NAME, true);
+        if (layoutName != null) {
+            // We may need to resolve the reference obtained.
+            layoutName = context.getRenderResources().findResValue(layoutName.getValue(),
+                    layoutName.isFramework());
+        }
+        if (layoutName == null) {
+             throw new InflateException("Unable to find action bar layout (" + LAYOUT_ATTR_NAME
+                    + ") in the current theme.");
+        }
+        return layoutName;
+    }
+
+    @Override
+    protected void setupActionBar() {
+        super.setupActionBar();
+        mActionBar.setupActionBar();
+    }
+
+    @Override
+    protected void setHomeAsUp(boolean homeAsUp) {
+        mActionBar.setHomeAsUp(homeAsUp);
+    }
+
+    @Override
+    protected void setTitle(CharSequence title) {
+        mActionBar.setTitle(title);
+    }
+
+    @Override
+    protected void setSubtitle(CharSequence subtitle) {
+        mActionBar.setSubTitle(subtitle);
+    }
+
+    @Override
+    protected void setIcon(String icon) {
+        mActionBar.setIcon(icon);
     }
 
     /**
      * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to
      * the content frame which shall serve as the new content root.
      */
+    @Override
     public void createMenuPopup() {
-        assert mEnclosingLayout.getChildCount() == 1
-                : "Action Bar Menus have already been created.";
-
         if (!isOverflowPopupNeeded()) {
             return;
         }
@@ -193,11 +188,6 @@
         return needed;
     }
 
-    @NonNull
-    public FrameLayout getContentRoot() {
-        return mContentRoot;
-    }
-
     // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth()
     private int measureContentWidth(@NonNull ListAdapter adapter) {
         // Menus don't tend to be long, so this is more sane than it looks.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java
similarity index 81%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java
index 6db722e..44c2cd8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java
@@ -19,10 +19,8 @@
 import com.android.annotations.NonNull;
 import com.android.annotations.Nullable;
 import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.SessionParams;
 import com.android.internal.R;
 import com.android.internal.app.ToolbarActionBar;
 import com.android.internal.app.WindowDecorActionBar;
@@ -54,10 +52,9 @@
 /**
  * A common API to access {@link ToolbarActionBar} and {@link WindowDecorActionBar}.
  */
-public abstract class CustomActionBarWrapper {
+public abstract class FrameworkActionBarWrapper {
 
     @NonNull protected ActionBar mActionBar;
-    @NonNull protected SessionParams mParams;
     @NonNull protected ActionBarCallback mCallback;
     @NonNull protected BridgeContext mContext;
 
@@ -68,49 +65,48 @@
      *                     ?attr/windowActionBarFullscreenDecorLayout
      */
     @NonNull
-    public static CustomActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context,
-            @NonNull SessionParams params, @NonNull View decorContent) {
+    public static FrameworkActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context,
+            @NonNull ActionBarCallback callback, @NonNull View decorContent) {
         View view = decorContent.findViewById(R.id.action_bar);
         if (view instanceof Toolbar) {
-            return new ToolbarWrapper(context, params, ((Toolbar) view));
+            return new ToolbarWrapper(context, callback, (Toolbar) view);
         } else if (view instanceof ActionBarView) {
-            return new WindowActionBarWrapper(context, params, decorContent,
-                    ((ActionBarView) view));
+            return new WindowActionBarWrapper(context, callback, decorContent,
+                    (ActionBarView) view);
         } else {
             throw new IllegalStateException("Can't make an action bar out of " +
                     view.getClass().getSimpleName());
         }
     }
 
-    CustomActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+    FrameworkActionBarWrapper(@NonNull BridgeContext context, ActionBarCallback callback,
             @NonNull ActionBar actionBar) {
         mActionBar = actionBar;
-        mParams = params;
-        mCallback = params.getProjectCallback().getActionBarCallback();
+        mCallback = callback;
         mContext = context;
     }
 
+    /** A call to setup any custom properties. */
     protected void setupActionBar() {
-        // Do the things that are common to all implementations.
-        RenderResources res = mContext.getRenderResources();
+        // Nothing to do here.
+    }
 
-        String title = mParams.getAppLabel();
-        ResourceValue titleValue = res.findResValue(title, false);
-        if (titleValue != null && titleValue.getValue() != null) {
-            mActionBar.setTitle(titleValue.getValue());
-        } else {
-            mActionBar.setTitle(title);
-        }
+    public void setTitle(CharSequence title) {
+        mActionBar.setTitle(title);
+    }
 
-        String subTitle = mCallback.getSubTitle();
+    public void setSubTitle(CharSequence subTitle) {
         if (subTitle != null) {
             mActionBar.setSubtitle(subTitle);
         }
+    }
 
-        // Add show home as up icon.
-        if (mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP) {
-            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
-        }
+    public void setHomeAsUp(boolean homeAsUp) {
+        mActionBar.setDisplayHomeAsUpEnabled(homeAsUp);
+    }
+
+    public void setIcon(String icon) {
+        // Nothing to do.
     }
 
     protected boolean isSplit() {
@@ -186,15 +182,14 @@
      * Material theme uses {@link Toolbar} as the action bar. This wrapper provides access to
      * Toolbar using a common API.
      */
-    private static class ToolbarWrapper extends CustomActionBarWrapper {
+    private static class ToolbarWrapper extends FrameworkActionBarWrapper {
 
         @NonNull
         private final Toolbar mToolbar;  // This is the view.
 
-        ToolbarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+        ToolbarWrapper(@NonNull BridgeContext context, @NonNull ActionBarCallback callback,
                 @NonNull Toolbar toolbar) {
-            super(context, params, new ToolbarActionBar(toolbar, "", new WindowCallback())
-            );
+            super(context, callback, new ToolbarActionBar(toolbar, "", new WindowCallback()));
             mToolbar = toolbar;
         }
 
@@ -248,19 +243,17 @@
      * Holo theme uses {@link WindowDecorActionBar} as the action bar. This wrapper provides
      * access to it using a common API.
      */
-    private static class WindowActionBarWrapper extends CustomActionBarWrapper {
+    private static class WindowActionBarWrapper extends FrameworkActionBarWrapper {
 
-        @NonNull
-        private final WindowDecorActionBar mActionBar;
-        @NonNull
-        private final ActionBarView mActionBarView;
-        @NonNull
-        private final View mDecorContentRoot;
+        @NonNull private final WindowDecorActionBar mActionBar;
+        @NonNull private final ActionBarView mActionBarView;
+        @NonNull private final View mDecorContentRoot;
         private MenuBuilder mMenuBuilder;
 
-        public WindowActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
-                @NonNull View decorContentRoot, @NonNull ActionBarView actionBarView) {
-            super(context, params, new WindowDecorActionBar(decorContentRoot));
+        public WindowActionBarWrapper(@NonNull BridgeContext context,
+                @NonNull ActionBarCallback callback, @NonNull View decorContentRoot,
+                @NonNull ActionBarView actionBarView) {
+            super(context, callback, new WindowDecorActionBar(decorContentRoot));
             mActionBarView = actionBarView;
             mActionBar = ((WindowDecorActionBar) super.mActionBar);
             mDecorContentRoot = decorContentRoot;
@@ -268,7 +261,6 @@
 
         @Override
         protected void setupActionBar() {
-            super.setupActionBar();
 
             // Set the navigation mode.
             int navMode = mCallback.getNavigationMode();
@@ -278,16 +270,6 @@
                 setupTabs(3);
             }
 
-            String icon = mParams.getAppIcon();
-            // If the action bar style doesn't specify an icon, set the icon obtained from the
-            // session params.
-            if (!mActionBar.hasIcon() && icon != null) {
-                Drawable iconDrawable = getDrawable(icon, false);
-                if (iconDrawable != null) {
-                    mActionBar.setIcon(iconDrawable);
-                }
-            }
-
             // Set action bar to be split, if needed.
             ViewGroup splitView = (ViewGroup) mDecorContentRoot.findViewById(R.id.split_action_bar);
             if (splitView != null) {
@@ -300,6 +282,17 @@
         }
 
         @Override
+        public void setIcon(String icon) {
+            // Set the icon only if the action bar doesn't specify an icon.
+            if (!mActionBar.hasIcon() && icon != null) {
+                Drawable iconDrawable = getDrawable(icon, false);
+                if (iconDrawable != null) {
+                    mActionBar.setIcon(iconDrawable);
+                }
+            }
+        }
+
+        @Override
         protected void inflateMenus() {
             super.inflateMenus();
             // The super implementation doesn't set the menu on the view. Set it here.
@@ -340,7 +333,7 @@
 
         @Override
         int getMenuPopupMargin() {
-            return -ActionBarLayout.getPixelValue("10dp", mContext.getMetrics());
+            return -FrameworkActionBar.getPixelValue("10dp", mContext.getMetrics());
         }
 
         // TODO: Use an adapter, like List View to set up tabs.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index fd976af..84ee914 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -51,11 +51,13 @@
 import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.android.SessionParamsFlags;
+import com.android.layoutlib.bridge.bars.BridgeActionBar;
+import com.android.layoutlib.bridge.bars.AppCompatActionBar;
 import com.android.layoutlib.bridge.bars.Config;
 import com.android.layoutlib.bridge.bars.NavigationBar;
 import com.android.layoutlib.bridge.bars.StatusBar;
 import com.android.layoutlib.bridge.bars.TitleBar;
-import com.android.layoutlib.bridge.bars.ActionBarLayout;
+import com.android.layoutlib.bridge.bars.FrameworkActionBar;
 import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
 import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
 import com.android.resources.Density;
@@ -354,7 +356,7 @@
 
                 // if the theme says no title/action bar, then the size will be 0
                 if (mActionBarSize > 0) {
-                    ActionBarLayout actionBar = createActionBar(context, params, backgroundLayout);
+                    BridgeActionBar actionBar = createActionBar(context, params, backgroundLayout);
                     actionBar.createMenuPopup();
                     mContentRoot = actionBar.getContentRoot();
                 } else if (mTitleBarSize > 0) {
@@ -1190,8 +1192,22 @@
         // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
         if (mIsThemeAppCompat == null) {
             StyleResourceValue defaultTheme = resources.getDefaultTheme();
-            StyleResourceValue val = resources.getStyle("Theme.AppCompat", false);
-            mIsThemeAppCompat = defaultTheme == val || resources.themeIsParentOf(val, defaultTheme);
+          // We can't simply check for parent using resources.themeIsParentOf() since the
+          // inheritance structure isn't really what one would expect. The first common parent
+          // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
+            boolean isThemeAppCompat = false;
+            for (int i = 0; i < 50; i++) {
+                // for loop ensures that we don't run into cyclic theme inheritance.
+                if (defaultTheme.getName().startsWith("Theme.AppCompat")) {
+                    isThemeAppCompat = true;
+                    break;
+                }
+                defaultTheme = resources.getParent(defaultTheme);
+                if (defaultTheme == null) {
+                    break;
+                }
+            }
+            mIsThemeAppCompat = isThemeAppCompat;
         }
         return mIsThemeAppCompat;
     }
@@ -1647,9 +1663,13 @@
     /**
      * Creates the action bar. Also queries the project callback for missing information.
      */
-    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params,
+    private BridgeActionBar createActionBar(BridgeContext context, SessionParams params,
             ViewGroup parentView) {
-        return new ActionBarLayout(context, params, parentView);
+        if (mIsThemeAppCompat == Boolean.TRUE) {
+            return new AppCompatActionBar(context, params, parentView);
+        } else {
+            return new FrameworkActionBar(context, params, parentView);
+        }
     }
 
     public BufferedImage getImage() {